Compare commits

..
Author SHA1 Message Date
sk89q ee2ed762c2 Added a better and more complete implementation for attributes with sane class names. 2013-02-07 12:11:25 -08:00
sk89q a0dceaa713 Added StringAttr.
The name of the class could be better.
2013-02-06 17:29:48 -08:00
sk89q 4b15855b2f Revert "Removed parents from regions."
Removal of parents will make upgrading extremely difficult and so consider them pending for the itme being.

This reverts commit df54d4de91.
2013-02-06 17:19:09 -08:00
sk89q 7acfb3586c Cleanup Attribute Javadocs. 2013-02-06 17:17:28 -08:00
sk89q a841aa7215 Added Stereotypes for group support for flags/attributes.
They are not yet functional because they require some extra mechanics not yet written (access to factories and whatnot).
2013-02-06 17:17:12 -08:00
sk89q f752c305d7 Made ApplicationRegionSet implement Collection<Region>, and made it keep the given list sorted. 2013-02-05 20:39:13 -08:00
sk89q 840700b719 Might as well make ApplicableRegionSet implement Collection<Region>. 2013-02-05 20:32:33 -08:00
sk89q 8f73a15ba3 Gutted ApplicableRegionSet. 2013-02-05 20:29:11 -08:00
sk89q 4e008f6c52 Made the class Javadoc of AbstractRegionQueryCache sane. 2013-02-05 20:20:31 -08:00
sk89q df54d4de91 Removed parents from regions.
After a minor discussion, parent-child relationships are being removed because they:
(1) confuse users
(2) make everything much more difficult to program
(3) do not allow for a use case that is not already doable with priorities
2013-02-05 20:06:11 -08:00
sk89q 0768e08e71 Minor cleanup. 2013-02-05 20:04:19 -08:00
sk89q 040e35f65b Added some misisng methods to DataValuedAttribute and added a test. 2013-02-05 16:25:59 -08:00
sk89q 919c03a57b Made Attribute abstract, rewrote Javadocs. 2013-02-05 16:16:45 -08:00
sk89q a13f556c7b Added AttributeTest. 2013-02-05 13:30:59 -08:00
sk89q 5bfb9e48f4 RegionTest cleanup. 2013-02-05 13:30:41 -08:00
sk89q ff209abb8c Added support for attributes to Region. 2013-02-05 13:18:46 -08:00
sk89q 7987258fe2 Added equals(), hashCode(), and toString() to Attribute. 2013-02-05 13:04:04 -08:00
sk89q 4cba9d01ec Replaced flags with attributes. 2013-02-05 13:00:44 -08:00
sk89q e703999c8f Added a simple test for com.sk89q.worldguard.region.Region. Flags are not yet tested. 2013-02-03 23:46:39 -08:00
sk89q bfc8691118 Added org.mockito:mockito-all v1.9.5 as test dependency. 2013-02-03 23:46:14 -08:00
sk89q 061b303faa Removed old broken unit tests.
We may look at them in the future once those tests are needed again.
2013-02-03 23:45:38 -08:00
sk89q 3b985f7eab Fixed potential resource leak in LegacyMySqlStoreFactory.getSql(). 2013-02-03 23:26:26 -08:00
sk89q a027721f37 Renamed RegionIndex.queryOverlapping() -> queryIntersects() and added an implementation under AbstractRegionIndex using IndexableShape.intersectsEdges(). 2013-02-03 23:24:32 -08:00
sk89q 129412ba79 Canning isOwnerOfAll() and isMemberOfAll() of ApplicableRegionSet. 2012-11-17 16:46:31 -08:00
sk89q e0ab79bd36 Canning RegionUtil, which is now completely useless. 2012-11-17 16:45:37 -08:00
sk89q 28a1f225ee Removed very broken and now irrelevant regions migration code. 2012-11-17 16:41:17 -08:00
sk89q 355168a3ac Removed isMember()/isOwner() as it is no longer relevant (to be placed with FlagResolvers). 2012-11-17 16:37:38 -08:00
sk89q 27c6819df9 Removed /claim. To be rewritten very differently. 2012-11-17 16:37:02 -08:00
sk89q 122c1aa003 Removed some left over CommandBook listener registration in WorldGuardPlugin. 2012-11-17 16:36:04 -08:00
sk89q 644d6ee512 Commented out regions-related code in ReportWriter as it is no longer valid. 2012-11-17 16:35:48 -08:00
sk89q 58cc4392c8 Removing RegionQueryUtil, which might not be needed anymore. 2012-11-17 16:35:24 -08:00
sk89q e228315dfd Removed CommandBook integration for /whois for now. 2012-11-17 16:35:03 -08:00
sk89q 8a308cd521 Remove old pre-5.x migration routines from WorldGuardPlugin. 2012-11-17 16:34:28 -08:00
sk89q c3d3c1812f Removing migration support for WorldGuard 4.x and below. 2012-11-17 16:33:37 -08:00
sk89q cc5958bc2f Removed FlagStateManager for now. To be added later. 2012-11-17 16:32:15 -08:00
sk89q 2d8911c9ce Added LegacyMySqlStoreFactory, moved .sql files to src/main/resources/sql. 2012-11-17 16:29:20 -08:00
sk89q c6a0c61028 Made LegacyMySqlStore compile. Domain not yet supported. 2012-11-17 16:28:54 -08:00
sk89q 0c0cbcc1b0 Added com.jolnox:bonecp as dependency. 2012-11-17 16:28:24 -08:00
sk89q 5882e30357 Add initialize() to RegionStoreFactory to allow some setup actions. 2012-11-17 16:27:50 -08:00
sk89q 4faf0a9b2e YamlStore needs to call reindex() after loading. 2012-11-17 16:27:25 -08:00
sk89q 2e4093e953 Removed FatalConfigurationLoadingException and InvalidTableFormatException. 2012-11-16 17:00:50 -08:00
sk89q 1a9a3274a6 YamlStoreFactory added.
Example usage:
StoreFactory factory = new YamlStoreFactory(new File("regions"), "worlds/%s/regions.yml"));
2012-11-16 16:42:37 -08:00
sk89q 8671fbc396 Implemented YamlStore.close(), which does nothing. 2012-11-16 16:41:05 -08:00
sk89q 50c4b3c738 RegionStore and RegionStoreFactory now extend Closeable. 2012-11-16 16:40:29 -08:00
sk89q 23f0791231 Changed MySQLStore to LegacyMySqlStore.
We're going to need a new MySqlStore that is not so poorly written. This is going to need a lot of work.
2012-11-16 16:07:34 -08:00
sk89q fa11dd6d62 Made YamlStore fit its interfaces so that there are no more compile errors.
It is, however, not yet ready, because it doesn't yet support custom flags or load in the old domain data.
2012-11-16 16:05:51 -08:00
sk89q 58fa6d1c0b Extracted RegionStore.save(Collection<Region> added, Collection<Region> updated, Collection<Region> removed) into PartiallyUpdatableStore.
This is necessary because some stores need to always save the entire database at a time (namely the YAML store), and adding an "all" parameter to the partial save method would mean that partial stores could not be supported in the future.
2012-11-16 15:52:37 -08:00
sk89q 723f17b782 Region indices now implement Collection<Region>.
In addition, PriorityRTreeIndex now extends FlatIndex! That should reduce some code duplication.
2012-11-16 15:40:09 -08:00
sk89q fe2e399451 RegionIndex now extends Iterable<Region>. 2012-11-16 13:49:33 -08:00
sk89q 6fa7faad12 Removed ProtectionDatabaseException and AbstractProtectionDatabase. 2012-11-16 13:43:14 -08:00
sk89q c864a1c252 RegionStore.save(Region added[], Region updated[], Region removed[]) throws IOException as well. 2012-11-16 13:42:59 -08:00
sk89q 386288b89a RegionStore's load() and save() methods can now throw IOExceptions.
ProtectionDatabaseException will be removed shortly.
2012-11-16 13:42:23 -08:00
sk89q b3425b2630 Region is no longer abstract, added Region.setFlagUnsafe(). 2012-11-16 13:39:26 -08:00
sk89q f8105c3de0 Fixed Javadocs for shapes. 2012-11-16 13:38:44 -08:00
sk89q bcf35085ed Indices now have a separate reindex() method because large changes to the index have to be supported.
Therefore, indices are no longer thread-safe. They don't need to be.
2012-11-16 13:36:26 -08:00
sk89q b7064cb102 Removed LegacyCsvStore and RegionDBUtil. 2012-11-16 10:12:59 -08:00
sk89q 6c282cfe0a Moved Region's package to com.sk89q.worldguard.region. 2012-11-16 10:11:08 -08:00
sk89q f8e0410d23 Finished com.sk89q.worldguard.region.shapes. 2012-11-16 09:28:46 -08:00
sk89q e8274e76ca Moved ProtectedRegion forward with some changes. 2012-11-15 17:17:56 -08:00
sk89q 393b15ac7a Added IndexableShape and its abstract brother. 2012-11-13 23:19:11 -08:00
sk89q 38f40908ee Say bye to com.sk89q.worldguard.domains.*. 2012-11-13 23:17:34 -08:00
sk89q caee1df596 Moved MySQLToYAMLMigrator to com.sk89q.worldguard.migration. 2012-11-13 01:03:24 -08:00
sk89q d9d655b6b2 Added RegionStore and RegionStoreFactory. 2012-11-13 01:02:41 -08:00
sk89q cc9bbec1c9 Added support for RegionIndexFactories. 2012-11-13 00:57:29 -08:00
sk89q 2a504ffbde Moved migration classes to com.sk89q.worldguard.migration. 2012-11-13 00:51:19 -08:00
sk89q 5f11c5710b Changed RegionIndex.{add|remove} to take in multiple regions to update, which may be faster for some index types. 2012-11-12 21:33:05 -08:00
sk89q 5d3409be57 Moved region.indexes package to region.indices. 2012-11-12 21:29:02 -08:00
sk89q ad921a2111 Updated the existing index code to work with the new RegionIndex interface. 2012-11-12 21:28:27 -08:00
sk89q 50ec8e5875 Added commons-lang:commons-lang:2.3 dependency. 2012-11-12 21:27:59 -08:00
sk89q fc9e28ddb9 Started with defining the new RegionIndex.
This definitely no longer compiles.
2012-11-12 20:08:34 -08:00
sk89q 35e02459ea Moved region classes to com.sk89q.worldguard.region. Preparing for some big changes.
The new classes will not (and should not) be backwards compatible, so the classes might as well be changed all around.
2012-11-12 01:24:34 -08:00
sk89q 0781ebc289 Added ?in-region and ?has-flag, and added the support to make protection models work. 2012-11-11 16:27:31 -08:00
sk89q 915e332a6b Fixed issue with block-place RL event not being given a source entity. 2012-11-11 16:26:34 -08:00
sk89q 19859164ab Moved settings loading in WorldConfiguration to loadSettings(), add preliminary loading of protection models. 2012-11-10 23:32:40 -08:00
sk89q bb7f972897 Added resource models/ to distributed JAR. 2012-11-10 23:32:12 -08:00
sk89q e355bb0055 Fixed missing exception message for an unknown action/criteria class in RuleEntryLoader. 2012-11-10 23:31:43 -08:00
sk89q 9b1b665da7 Removed some chest protection code, which will be replaced with RuleLists. 2012-11-10 22:35:57 -08:00
sk89q 6daf80229d Fixed condition issue in EntityCriteria that broke entity type checking. 2012-11-10 21:29:31 -08:00
sk89q dc1f3f54b1 Redesigned how RuleLists were compiled and created to be less roundabout. 2012-11-10 21:29:00 -08:00
sk89q 579143a5dd Added support for the region query cache on Bukkit's side and added it to BukkitContext. 2012-11-10 10:48:25 -08:00
sk89q f4e52f5cd7 Added Javadocs to BukkitContext. 2012-11-10 00:31:50 -08:00
sk89q abea9689cb Removed blacklist/region code for now, to be converted to RuleLists.
Additionally, a chat rule list event was added, the vehicle destruction event was routed to rule lists, and so was the bed enter event.
2012-11-09 14:49:45 -08:00
sk89q 2c7767f89f Added RegionQueryCache, which will be used to for cached regions-contain-point lookups. 2012-11-09 12:18:54 -08:00
sk89q 5e75bf36c3 Added proposed protection models. 2012-11-06 22:04:25 -08:00
sk89q a5814c4b32 Made the resolution of criteria parameters as all logical ANDs. 2012-11-06 10:29:41 -08:00
sk89q 70ae1c46a2 Fixed incorrect warning about unrecognized "entity" parameter in TellActionLoader. 2012-11-06 00:52:44 -08:00
sk89q fc5c59ec85 Added support for the item attribute of the Context and routed PlayerInteract into item-use,. 2012-11-06 00:51:40 -08:00
sk89q 2d9a28b0e6 Support accessing the item attribute of the context with match-item and update-item. 2012-11-04 16:07:42 -08:00
sk89q cbcc524798 Standardize the default resolver of entities/blocks to 'target'. 2012-11-04 13:00:52 -08:00
sk89q 69940f2fac Standardized default resolver values. 2012-11-04 12:33:35 -08:00
sk89q 35628d09be Route BlockDispenseEvent to RuleLists item-drop. 2012-11-04 12:17:05 -08:00
sk89q ef43ba2700 player-spawn -> player-join 2012-11-04 11:05:21 -08:00
sk89q 2c2484b026 player-death is very redundant. Changing to entity-death. 2012-11-04 11:03:40 -08:00
sk89q b181bfc914 Added dynamics.disable-mycelium-spread to match master branch. 2012-11-04 01:03:08 -08:00
sk89q 7fcf686d8d Added physics.vine-like-rope-ladders to make ladders work like vines. 2012-11-03 23:28:35 -07:00
sk89q 4f5a751519 Added RuleLists, which are a more flexible version of blacklists, with a cleanup of code.
RuleLists abstract events, and provide a way to unify WorldGuard's various code paths eventually.

There's also a general cleanup of everything and added support for changing the per-world configurations and blacklists (fixes WORLDGUARD-2232). WORLDGUARD-2203 is implicitly fixed by this, although not entirely fully as this does not yet replace blacklists.

Most configuration settings have been rewritten as RuleList rules and can be found in src/main/resources/builtin_rules.yml. Some configuration changes were made: anti-wolf-dumbness was deprecated in favor of wolves-practically-invincible, and ocelots-practically-invincible was added.

Sponges can now re-place water when they are removed, fixing WORLDGUARD-2202.
2012-11-03 23:21:32 -07:00
534 changed files with 21012 additions and 48425 deletions

No files matched your search

+2 -2
View File
@@ -1,2 +1,2 @@
*.java diff=java
*.java diff=java
+2 -13
View File
@@ -1,17 +1,6 @@
.classpath
.project
.settings/
target/
.settings
target
.DS_Store
**/*.iml
**/.idea
bin/
dependency-reduced-pom.xml
*-private.sh
.gradle/
**/build/
out/
+4 -5
View File
@@ -1,8 +1,7 @@
language: java
dist: trusty
jdk:
- oraclejdk8
- oraclejdk7
- openjdk7
- openjdk6
notifications:
email: false
before_install: chmod +x gradlew
script: ./gradlew build -S
email: false
-915
View File
@@ -1,915 +0,0 @@
# Changelog
## 7.0.1
* Add `/rg toggle-bypass` command which temporarily turns off region bypassing until used again.
* More improvements to `/rg flag` and `/rg flags` commands.
* Fix some checks for adding owners to unclaimed regions.
* Fix an issue with time-/weather-lock flags when logging in to a region with the flag set.
* Fix cause tracking in vehicles (incl. breaking lilypads in a boat)
* Use async teleports on Paper.
* Include hopper minecarts in the ignore hoppers config setting.
* Add sugar cane and cacti to the crop-growth flag. Bamboo is also included pending Spigot throwing an event for it.
* Specifically track when players ignite creepers with flint and steel.
* Fix fuzziness when using bonemeal near a protected region.
* Fix color codes not applying in greeting, etc flags when placed after a newline (\n).
* Add applicable region information to `/wg report`.
* Fix pistons flag not applying to sticky pistons pulling blocks.
* Add some custom metrics for bStats.
* Everything in the RC/beta changelog below.
## 7.0.1 RC 2 (inc. beta 1)
* Due to breaking changes in important Bukkit API, this is not compatible with MC 1.13!
* Update to MC 1.14. Adds protection for new blocks, etc.
* To allow players to read from lecterns, but not take the book, flag interact allow, and then flag chest-access -g nonmembers deny.
* Add ravager-grief flag.
* Fix overprotection of unsaddled pigs with the ride flag.
* Fix lava fire defaulting to off (won't change existing configs).
* Fix damaged/chipped anvils not respecting use flag like regular anvils.
* Add on-equip blacklist event. Note that it is overprotective due to deficiencies in Bukkit API.
* Update WorldEdit CUI when using /rg select.
* Add config option to disable villagers getting zapped into witches. ("weather.disable-villager-witchification")
* Add entity support to interact-whitelist config option (use the Material of the corresponding item).
* Fix vehicle-place protecting the rails at the very top of region boundaries incorrectly.
* Fix for emptying buckets on waterloggable blocks.
* Whitelist all player -> player interactions (previously was spammy in pvp).
* Fix sleep flag not protecting against explosions in nether/end.
* Add config for the teleport-on-void to reset fall distance.
* Fix config options taking material lists requiring "minecraft:" namespace.
* Fix disallowed-lightning-blocks situationally not working.
* Fix errors that occurred when plugins used falling block entities with non-item materials.
* Add special support for Paper servers (papermc.io): Paper's API allows us to track who launched fireworks.
* Fireworks are now protected by default. On Paper servers, members can use them by default (to deal damage),
on non-Paper servers, flag firework-damage allow to revert to old behavior (everyone can deal damage with fireworks by default).
* Misc performance enhancements for Paper servers.
* Add 'regions.use-paper-entity-origin' as an experimental setting (default off) for Paper servers. Enabling it will make non-player entities be treated as members of the place they spawned, instead of their current location when flags are checked.
## 7.0.0
* Added support for MC 1.13, dropped support for previous versions.
* Added lots of interactive text in e.g. `/rg info` command.
* Added `/rg flags` command which allows viewing and interactively setting all flags on a region.
* Large behind-the-scenes changes to WorldGuard's API (developers, see https://worldguard.enginehub.org/en/latest/developer/)
* Places that used numeric block ids (e.g. blacklist) should now use Minecraft's new string IDs.
* Fix various interactions with NPCs and region protection.
* Sponge-simulation now destroys kelp and seagrass, and de-waterlogs blocks.
* Added an option to block conduit effects.
* Fix using newlines in string flags such as greeting and farewell.
* Add item-frame-rotation flag.
* Ender chests no longer require chest-access (since they don't have inventories).
* Add kelp to vine-growth flag/config.
* Add block-trampling flag (for turtle eggs and farmland).
* Add snowman-trails flag.
* Track potion area-of-effect cloud causes for pvp etc. protection.
* Add confirmation to /stoplag command.
* Forcefully eject players from vehicles trying to force their way into entry deny regions (and out of exit deny).
* Fix removing child regions when removing a region with children.
* Fix some over-protectiveness of pistons.
* Chat and command flags (send-/receive- and allowed-/blocked-) now respect deny-message flag.
* Misc fixes.
## 6.2.2
* Added support for MC 1.12.
* Changed flower pots to fall under the build flag.
* Fix heal flag not functioning.
* Add option to allow Forge clients with host-keys setting.
* Add mobs.block-armor-stand-destroy config.
* Add firework-damage flag.
* Add config option to ignore hopper checks.
* Misc fixes.
## 6.2
* Added support for MC 1.11.
* Add a custom flag and session API (for developers, see https://worldguard.enginehub.org/en/latest/developer/)
* Add a config option to ensure location flags (teleport, spawn) are inside their region.
* Misc fixes.
## 6.1.2
* Added support for new blocks in 1.8, 1.9, and 1.10.
* Added protection from nether portals being created in protected region (enable via config `nether-portal-protection`).
* Added protection from slime block piston contraptions pushing into or pulling from regions.
* Added `chorus-fruit-teleport` flag, works similar to `enderpearl` to prevent teleportation.
* Added protection from pulling armor stands, items, and entities from protected regions.
* Changed order of greeting and farewell flags on adjacent regions. When leaving a region with a farewell flag and entering one with a greeting flag, the farewell message will be shown first now.
* Changed /heal command to also fill food/saturation meters.
* Changed fall damage prevention to also prevent flying into walls with elytra being fatal.
* Fixed fire-spread flag only preventing destruction, now prevents spreading too as per its name.
* Fixed creepers targeting players being able to blow things up in certain cases.
* Fixed armor stands being removed by /stoplag.
* Fixed some issues with fireballs being able to explode when ghast-fireball was set to deny.
* Fixed a lot of other minor issues.
## 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.
* Added a visual smoke effect when an action on a block has been denied.
* Added `event-handling.interaction-whitelist`, a list of items or blocks that should never be protected. For example, adding `wooden_door` to the list would make it so that doors could be used by anyone regardless if they have permission or not. You may still protect the blocks via other means.
* Added `event-handling.emit-block-use-at-feet`, a list of items that, when used, will also be considered as the player using that item on the block at the player's feet. The purpose of this setting is, for example, to allow you to (sort of) prevent the use of a mod-added item that does not emit events.
* Added `-s` to silently turn toggle `/stoplag` and `-i` to show the current state of the setting. (Thanks, [stuntguy3000](https://github.com/stuntguy3000)).
* Added support for Bukkit [Material](http://jd.bukkit.org/rb/apidocs/org/bukkit/Material.html) names in the blacklist.
* Fixed [#3167](http://youtrack.sk89q.com/issue/WORLDGUARD-3167): Saplings can be used without permission although it won't place blocks inside the region
* Fixed [#3168](http://youtrack.sk89q.com/issue/WORLDGUARD-3168): Grown saplings that are partially prevented from placing all of its leaves may not remove the sapling
* Fixed [#3169](http://youtrack.sk89q.com/issue/WORLDGUARD-3169): Bonemeal usage falls under the USE flag when it should really fall under building
* Fixed [#3174](http://youtrack.sk89q.com/issue/WORLDGUARD-3174): Boat placement is not properly prevented in a protected region
* Fixed [#3130](http://youtrack.sk89q.com/issue/WORLDGUARD-3130): Polygonal selections allow unlimited claim volumes with /rg claim
* Fixed [#3137](http://youtrack.sk89q.com/issue/WORLDGUARD-3137): Claiming infinite regions is possible due to integer overflow
* Fixed [#3171](http://youtrack.sk89q.com/issue/WORLDGUARD-3171): Can't pickup XP in protected regions without permission
* Fixed [#3170](http://youtrack.sk89q.com/issue/WORLDGUARD-3170): Boats without a driver can be used to break lily pads
* Fixed [#3172](http://youtrack.sk89q.com/issue/WORLDGUARD-3172): Players cannot be damaged by mobs in protected regions unless they have permission
* Fixed [#3152](http://youtrack.sk89q.com/issue/WORLDGUARD-3152): BUILD overrides all other flags, unlike in WG 5
* Fixed [#3154](http://youtrack.sk89q.com/issue/WORLDGUARD-3154): notify-enterflag doesn't work with horses and other vehicles
* Fixed [#3166](http://youtrack.sk89q.com/issue/WORLDGUARD-3166): Trees do not grow naturally within protected regions
## 6.0 beta 1
### UUID support
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.
Only one "category" of flags needs to evaluate to true to permit an action. `DENY` will not cross categories. For example, if `BUILD` is deny, it will not override `SLEEP`, so if `SLEEP` is set to `ALLOW`, sleeping will be permitted. This is fairly similar to how it worked on WorldGuard 5.
### 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
* Added a setting to permit "fake players" to bypass protection. Fake players are used by some servers and some mods to allow events to be thrown for mod blocks. WorldGuard considers a player to be a fake player if the name starts with `[` and ends with `]`.
* Added a check so players can no longer disembark in a region from their tamed animal if they don't have permission to get back on.
* Added an item pickup flag to go along with the item drop flag.
* Added a new `//running` command was added to show currently running background tasks.
* Added a blacklist `on-dispense` event.
* Added more detailed error messages when parsing the YAML regions file.
* Added the `-Dworldguard.debug.listener=true` option that can be set on your server's command line to see how WorldGuard processes events, although this will result in a lot of log messages.
* Added log messages that occur on player join when a player had auto-god mode or auto-amphibious mode.
* Fixed the heal command so that it now sets a player's health to the maximum rather than 20.
* Fixed `ProtectedCuboidRegion.getPoints()` returning points in wrong order.
* Fixed the obsidian generator disable option to also apply to tripwire.
* Fixed an error with the blocked commands flag.
* Fixed a connection leak with the MySQL region code.
* Fixed `/wg reload` sometimes not applying new changes right away.
* Changed the region removal command so that child regions are no longer removed without warning when removing the parent region.
* Changed the YAML region data save code to first write the data to a temporary file before replacing the final file.
* Changed how region data is handled when region support is disabled: it is no longer loaded.
* Changed sponges to now be disabled by default. However, if you had previously installed WorldGuard, sponges will still be enabled. Sponges are being added in Minecraft and they work differently than in Minecraft Classic (which WorldGuard emulates). In addition, enabling sponge support in WorldGuard incurs extra CPU cost even if no sponges exist in the world.
* Changed how region data is loaded and saved so failures are now more graceful. If the region data fails to load for a world, then the entire world will be protected by default. In addition, periodic attempts will be made to load the region data in the background.
* Changed the `FEED` flag to maximize the player's saturation level if the hunger level is raised.
* Changed the `wg-invincible` and `wg-amphibious` groups feature so that it now must be enabled in the configuration.
* Removed the ability for WorldGuard to upgrade from a version for Minecraft Alpha.
### API changes
* You can use a new `WorldGuardPlugin.createProtectionQuery()` method to easily check build permissions.
* The listener classes were moved. Consider them internal -- if you want to make use of the listener somehow, please put in a ticket in our issue tracker.
* Much of the protection-related handling was previously scattered throughout the code. Now WorldGuard funnels events into an internal event system and then processes protection queries in a more consistent matter. These events are for internal use so it is strongly recommended that you do not use them (they may change without notice drastically). A lot of the protection-related flag handling was moved there.
* A significant portion of classes under the package of `com.sk89q.worldguard.protection` were changed or removed. However, the basic calls (testing the value of a flag, etc.) should still work, but they may be deprecated. Some of the utility `Domain`-related classes were removed.
* The old region database (load/save) API was removed and replaced with a new one. The new one no longer needs to pointless store a collection of regions on itself -- it has `collection = load()` and `save(collection)` methods.
* Previously, there were subclasses of `RegionManager` that implemented different spatial indices. However, now `RegionManager` is a final class and the spatial indices are separate (see the `RegionIndex` interface).
* A hash table was implemented that caches a list of regions within each loaded chunk. This increases performance of spatial queries substantially.
* A cache of recent spatial queries now exists (a cache of `ApplicableRegionSets`), but you need to make use of `RegionQuery` to make use of this cache. However, if you need to do a spatial query to modify region data, then the old method is better (get a `RegionManager`, etc.).
* `ApplicableRegionSet` was converted into an interface. In addition, there are now "virtual" `ApplicableRegionSet` instances that are returned by `RegionQuery` for certain special cases (such as, for example, region support being disabled by the user or region data being unavailable for a world due to an error). A new `isVirtual()` method is available. This is not an issue if you are getting `ApplicableRegionSet` instances from a `RegionManager`.
* `ApplicableRegionSet` now can accept a pre-sorted collection and its use of a `TreeSet` was removed for performance reasons.
* `FileNotFoundException` is now properly handled in the YAML region file class. It creates the new file and continues on.
* Player names are deprecated by Mojang and so they need to be converted into UUIDs. As this will take some time, you should do this conversion in a background task. To check whether a region contains a player, it recommended that `contains(LocalPlayer)` be used because it's possible that the user may be still using names. A new `WorldGuardPlugin.wrapOfflinePlayer()` method was added for this specific purposes.
* All flags now use `RegionGroup.ALL` as the default region group.
* `StateFlag.getDefault()` now returns a `State` rather than a `boolean`.
* The priority R-tree index now uses the R-tree for region intersection queries. Previously, it was only used for single point containment queries.
* Regions now keep a "dirty" flag and changes it whenever data within the region is changed. When WorldGuard decides to periodically save region data, it may only save changed regions. Calling `save()` on the `RegionManager` is no longer needed as periodical saves happen automatically.
* The old region data migration API was removed in favor of region store drivers. There is no longer a need to have an implementation for every possible conversion (i.e. YAML -> MySQL, MySQL -> YAML, etc.).
* `ProtectedRegion.copyFrom()` was added to copy region settings from another region.
* `@Nullable` annotations were added throughout the code. If you use IntelliJ IDEA, you may notice that it now warns you when a return value may be `null`.
## 5.9
* Added a config option to allow explosion flags to only prevent block damage
* Added allow-tamed-spawns setting, on by default. This will stop WorldGuard from culling tamed animals.
* Added config option and flag to prevent soil from drying naturally.
* Added formatting codes, &k/l/m/n/o and &x (reset).
* Added snow-fall-blocks option to config to restrict snow fall to certain blocks
* Allow players to add newlines (\n) via command, not just manually in yml.
* Allow the console to load/save all region managers with one command.
* Changed entity report format slightly.
* Check bypass perms for item-drop flag.
* Check for entities and projectiles removing items from frames too.
* Fix being able to use bonemeal to turn tall grass into double plants.
* Fix number of arguments for migratedb command.
* Fixed addowner/addmember commands adding command artifacts. Specifically, "-w <world>" will no longer be added when using it.
* Fixed milking cows in protected areas due to changes in Bukkit.
* Fixed ProtectedCuboidRegion::getPoints() returning points in wrong order.
* Fixed snowman trails being treated as snow fall.
* Make /rg list default to own regions if the player doesn't have permission otherwise.
* Protected items in item frames in protected regions.
* Resolved an issue where explosions of type OTHER_EXPLOSION were ignoring the world configuration settings.
* Send item-use blacklist event when right-clicking entities.
* Transformed the BlockFadeEvent handler into a switch.
## 5.8
* BREAKING CHANGE: This version has been built for versions of Bukkit for MC 1.6.1 and newer. Do not try to use this version of WG on an older Bukkit version.
* Added support for Minecraft 1.6+. Actual support of new 1.6 additions is dependant on Bukkit. Please use a newer build of Bukkit if, for example, you seem to be unable to add "Horses" to your lists of entities.
* Added mobs.disable-snowman-trails to disable the trails left by walking snowmen.
* Added -a flag to /region removeowner and /region removemember to remove all objects.
* Teleporting is now handled by entry/exit flags. If this is causing people to get entirely stuck inside entry/exit deny regions, set the new setting 'use-player-teleports' to 'false' in your configuration.
* Updated formatting for region commands, especially /region info.
* Changed permissions checking for /region commands to be more consistent, checking for region IDs as a sub-node. This means that if some permissions for some region commands no longer work, add '.*' to the end of permission lines for WG in your permission plugin.
## 5.7.5
* Refixed a few issues from 5.7.4.
## 5.7.4
* BREAKING CHANGE: Removed the cyan "**" in front of greeting and farewell messages to allow more customizability. You can re-add them by adding "&c**" to the flag.
* Fixed an issue enderpearling inside exit/entry deny regions.
* Added checks to players teleporting in and out of exit/entry regions.
* Fix bad matching in blocked and allowed command flags.
* Fixed heal flag bugs when player max health was increased.
* Add fishing to xp blocker.
* Applied other-explosion flag to entity damage as well.
* Fixed an issue with interaction that should allow blacklisting item use actions with no block involved (eg fishing rods, potions)
* Fix witherskull/fireball settings not being differentiated in one case
* Allow cow milking in no-build areas
* Fix infinite durability breaking items instantly.
## 5.7.3
* Fixed the error caused by Bukkit's change of the TNT minecart API.
## 5.7.2
* Updated to MineCraft 1.5.
* Added TNT Minecart support. They are handled with the same flags/settings as TNT.
* Added mining and smelting xp handling to the xp drops flag and setting.
* Fixed a few edge cases for placing items on region borders.
* Legacy: Fixed issue with //stack not respecting item metadata.
## 5.7.1
* Added a vine growth config option and flag.
* Added support for many commands to be used from console. Usage is with -w flag and a world name e.g. /rg addmem <id> <player> -w <worldname> /rg flag <id> <flag> -w <worldname> <flagvalue>
* Fixed bug that blocks placing plants in flower pots.
* Fixed permissions check for /rg tp
* Fixed enderchests not being accessible (they are now part of the USE flag)
* Fixed an issue with slabs being placable in protected regions. This was also fixed in CraftBukkit but has been left in for users running other versions.
* Fixed wither skulls being handled with other fireballs, despite having their own settings.
* Fixed item frames being placable on region borders.
* Fixed a bug that made explosions more ineffective than they should have been.
* Fixed bonemeal usage in protected regions.
* Fixed special minecarts being placable in protected regions.
* Fixed bugs being placable on region borders.
* Fixed wolves bypassing pvp flags.
## 5.7
* Fixed thread sync issue with FlagStateManager.
* Fixed dragon egg region protection not working in certain cases.
* Added beacon and anvil usage protection in regions.
* Add mobs.block-enderdragon-portal-creation to stop enderdragons from making portals on death.
* Fix TNT being lethal in some case when damage was disabled.
* Fix snowballs and enderpearls being able to knock players back in pvp deny regions.
* Add subcommand support for allowed and blocked command flags.
* Add max-players-allowed and max-players-reject-message flags to limit the numbers of players in a region.
* Fix players being able to plant cocoa beans in protected areas.
* Add an enderpearl flag to prevent players from teleporting to and from regions.
* Added mobs.block-other-explosions config setting and other-explosion flag to block explosions caused by uncovered things, such as other plugins. (It doesn't actually have to be a mob)
* Fix mob damage setting and flag not blocking the DoT wither effect.
* Ghast fireball flag will not block blaze fireballs from lighting things on fire.
* Fixed players without region permissions being able to trigger tripwires, use enderchests, use wooden buttons, and put plants in flower pots.
* Added mobs.block-zombie-door-destruction setting to stop zombies from breaking down doors while difficulty is set to hard.
Thank you to thvortex, Dilandau, tophathacker, and Dark_arc for their contributions this release.
## 5.6.5
* Fixed a regression that caused paintings and item frames to no longer be properly protected.
## 5.6.4
* Added mobs.block-above-ground-slimes to block slimes spawning naturally above ground.
* Added security.deop-everyone-on-join to de-op all players when they join.
* Added security.block-in-game-op-command to prevent usage of /op from in-game.
* Fixed a NullPointerException in PlayerInteract involving water potions and potion blocking.
* Fixed an issue with snowballs being blocked in regions.
* Changed dragon eggs to be checked like it is a broken block in regions.
* Moved developer's WGBukkit class to package com.sk89q.worldguard.bukkit.
## 5.6.3
* Added helper WGBukkit class to get references to WorldGuard from other plugins.
* Added physics.vine-like-rope-ladders to make ladders work like vines. As long as the top ladder block is present, ladder blocks will hold even if they have no block behind them, like a rope ladder.
* Fixed NullPointerException in PlayerInteractEvent caused by potion blocking.
* Fixed mobs.block-{item-frame,painting}-destroy not working.
Thank you to def for testing the above fixes and features.
## 5.6.2
* Fixed potion blocking not working well for splash potions.
## 5.6.1
* Added a mycelium-spread region flag.
* Added a dynamics.disable-mycelium-spread configuration setting.
* Added new gameplay.block-potions option. For example: gameplay: block-potions: [invisibility, speed]
* Fixed a bug in the entity explosion event handler that caused a NullPointerException.
Thank you for gabizou for his contribution in this release.
## 5.6
* Added official support for Minecraft 1.4. Support for 1.3.2 (and below) is still provided in this release.
* Added support for new and existing explosion types.
* Added support for blocking withers with the following settings: mobs: block-wither-explosions: false block-wither-block-damage: false block-wither-skull-explosions: false block-wither-skull-block-damage: true
* Added support for blocking item frames (and their use) in protected regions.
* Added item frame destruction region flags (if you wish to disable item frame destruction completely).
* (Re-)added support for priority R-tree region indexes. This means quicker region lookup, and better support for servers with thousands of regions.
* Improved /region info output for -g group flags.
* Allowed removing of -g group flags with /region flag.
* Allowed /region flag to set group and value at once.
* Deleting a region flag now also deletes group flag.
* Fixed detection of attack by projectiles to be more accurate.
* Fixed support for saving non-string flags in the MySQL region support.
* Fixed spurious comma in "Flags:" /region info output.
* Fixed players who are not in god mode not receiving damage in PVP areas from enderpearls.
* Players will now be told that they are in a no-PvP area if they are in one and attempting to attack someone, or that the player they are attacking is in a no-PvP area, if that is the case instead.
* Fixed an issue where region.getId() was lowercase'd each pass of a for loop in MySQLDatabase.updatePoly2dPoints().
* Fixed mob damage from projectiles not being properly blocked in regions where applicable.
* Changed default region wand to leather (#334).
Thank you to the following individuals for their contribution:
thvortex, Rutr, Glitchfinder, and DarthAndroid.
## 5.5.4
* Minecraft 1.3 support.
* Fixed /stack dupe bugs.
* Added regions.use-creature-spawn-event.
* Update for Async chat issue.
* Add use flag to cakes.
* Report number of plugins loaded in report writer.
* Updated fireblal item blocking.
* Fixed permissions for /region reload.
## 5.5.3
* Added game mode flag.
* Added item drop pickup flag to regions.
* Added support for fireball item blocking (385).
* Added configuration option to allow creature spawns from plugins.
* Added host key check.
* Added a new line split feature to region greetings.
* Prevented commands in the allow commands list from being blocked and vice versa.
## 5.5.2
* Added potion-splash flag to block splash potions
* Add entity-painting-destroy which can be used to prevent entities from destroying paintings (skeletons firing arrows)
* Added send-chat and receive-chat flags
* Fixed having regions in multiple worlds with the same name not working with MySQL
* A cancellable event is now fired if WorldGuard disallows PvP. (for developers!)
* Made /region setparent check worldguard.region.setparent.own/member.<parent> instead of worldguard.region.setparent.own/member.<child>.
* Allowed passing #<index> in place of a region ID, where <index> is the index as displayed by /region list.
* Fixed an error that occured when clearing a non-existant region's parent.
* Added a -s flag to /region teleport, which sends you to the spawn point instead of the teleport point of a region.
* Added region/role-based permissions to /region teleport.
* BREAKING CHANGE: Added a LocationFlag class and made the teleport and spawn flags use it.
* /region info -s now selects the region being queried.
* Added /region teleport <id>.
* Vector flags can now be set to the current location with the value "here" and to a specific position with x,y,z.
* Made /region info show the region you're in if you don't specify an id explicitly.
* Prevent block ignition from lightning strikes if lightning is blocked in region. Fixes #1175
* Correctly check both WEPIF and superperms in WorldGurdPlugin.broadcastNotification()
* Destroy fire blocks when fire-spread is disallowed
* Added a construct flag that can be used to restrict block placing/destroying in zones to certain roles.
* Added FallingSand to list of intensive entities to be removed with /halt-activiy.
* Replaced all usage of CreatureType by EntityType.
* Updated to support Bukkit 1.2-R0.3 and newer
* Made auto-god-mode disabled by default again.
* Added sign protection check disable.
* Cleaned up javadoc, deprecated duplicate methods, other cleanup
* Added a RegionGroupFlag to evey region flag Using the /region flag command with -g, the region group that the region flag applies to can be set.
## 5.5.1
* Fixed attacking with arrows from non-PVP to PVP areas
* Compatibility with Bukkit 1.1-R5
* Removed broken suppress-tick-sync-warnings config option. See bukkit.yml's setings.warn-on-overload option instead.
* Add region and 'can build' information to CommandBook's /whois
Contributions thanks to: NolanSyKinsley
## 5.5
* Removed WorldEdit.jar from the classpath to stop conflicts with Bukkit's plugin loader
* Now using Bukkit's tagged logging
* Updated to new event system
* Flush player flag state cache on world change
* Improved compatibility with versions of CommandBook without GodComponent and updated pom dep for 2.0
* Added MySQL region storage method.
* Made explosions display their animations even when the event was blocked.
* Added fallback support for those who don't have a version of CommandBook with GodComponent
* Added LIGHTNING flag to DefaultFlag's flagsList Fixes #1026
* Removed /god, /heal, /locate, and /stack from WorldGuard to CommandBook. CommandBook is now checked to see whether a player is godded.
* Removed remaining usages of org.bukkit.util.config.Configuration
* Removed some unused configuration options
* Added permission worldguard.region.wand to the region wand
* Fixed ProtectedRegion.compareTo.
* Fixed FlatRegionManager.getApplicableRegions to return parent regions as well.
* Added exp-drops flag to disable experience drops per-region.
* Fixed some warnings.
* Updated dependency version for WorldGuard from 5.0 to 5.1-SNAPSHOT.
* Added support for fireballs shot by players being blocked by the PVP flag.
* Now using dynamic command registration
* Split off ender dragon block damage from creeper block damage.
Contributions thanks to: narthollis, DarkArc, Wolvereness, and skeight
## 5.4
* Fixed configuration generation on Windows
* Fixed intersection calculation for regions
* Fixed timer and feeding delay for food flags
* Fixed region managers not being created properly (This caused errors related to CREATURE_SPAWN)
* Added support for Minecraft 1.0.1 blocks
* Added support for enchantments and tool damage (worldguard.stack.damaged is the node) with /stack
* Made being in the wg-invincible group respect the configuration's auto-invincible setting
* Added per-group region claim limit maximum
* Added worldguard.region.addowner.unclaimed.* permission for non-economy region 'buying'
* Checking allowed/blocked commands now occurs earlier to override more plugins
* Made PVP flag check whether either player is in a pvp deny region for blocking
Contributions thanks to: epuidokas, wizjany, Turtle9598, and DerFlash
## 5.3
* Added new config options and flags to better handle explosions of all types
* Added config options and flags for snow, ice, mushroom spread, grass spread, and leaf decay
* Added min and max health flags to clamp the values for the existing healing flags
* Added hunger flags similar to the existing healing flags
* Added an option to disable the use of the move event. This can boost performance on large servers but will disable the greeting/farewell and entry/exit flags
* Added flag to prevent pistons (including those that are outside the region, but would affect blocks inside the region)
* Added a /wg flushstates [player] command to free players stuck in a region that was exit-deny but no longer exists or the flag was removed
* Added a config option to disable xp orb dropping
* Added config option to disable redstone wire obsidian generators
* Added a vehicle-destroy flag
* Added enderman protection config and flag
* Allowed and blocked command flags will now fall back to the global region
* The worldguard.region.flag.own/member permissions are now worldguard.region.flag.regions.own/member! Please change your permissions accordingly.
* Made //stack respect max stack sizes unless the player has the worldguard.stack.illegitimate permission
* Setting invincibility flag to deny will override god mode unless the player has worldguard.god.override-regions
* The sleep flag will now prevent beds in the nether from exploding if set to deny
* Existing regions can no longer be accidentally overwritten. Use /region redefine to move an existing region.
* The info command will now sort players alphabetically
* Priming TNT by punching it with flint and steal should throw a blacklist event (consistent with old Minecraft versions)
* The /stoplag command will now remove xp orbs
* Permissions system will use per-world permissions if the provider supports it
* Players in vehicles are now subject to entry/exit and greeting/farewell flags
* Fixed interact blacklist event not logging correctly
* Fixed heal flag taking effect half a block northeast of the region
* Fixed a infinite sign dropping bug
* Fixed players being able to douse fire by punching it in regions they couldn't build it
* Fixed players being able to eat protected cake
* Fence gate usage can be blocked with the use flag
* Fixed chests being unprotected when they should be in 1.8
* Fixed weather config settings not applying when a world was loaded
* Fixed explosion handling in certain cases
* Fixed arrows working in non-pvp zones
* Fixed buckets working on the border of protected regions in certain cases
Contributions thanks to:
wizjany, zml2008, imjake9, Droolio, epuidokas,
EduardBaer, TomyLobo, and halvors
## 5.2.2
* Changed configuration saving so empty lists will be added to the configuration files.
## 5.2.1
* Add region bounds to /region info
* Added the ability to add owners/members to the global region for handling guest groups. Now if there's owners or members on the global region, then those that are not on the list cannot build.
* Fixed some flag algorithm issues.
* API: Fixed DefaultDomain.size() not counting players.
* API: Undeprecated ApplicableRegionSet.allows(StateFlag).
## 5.2
* Gave the ability to use color colors and macros in greeting and farewell messages.
* Added disable-ice-melting, disable-snow-formation, disable-mushroom-spread, disable-snow-melting, disable-ice-formation.
* Added paintings to blacklist support.
* Added default.disable-health-regain.
* Added auto-invincible-permission setting, which lets you use the permission 'worldguard.auto-invincible' to become invincible on join automatically.
* Flames won't appear if you are /god'ed now.
* Added blocked-cmds region flag to block commands.
* Added allowed-cmds region flag to whitelist commands.
* Added entry region flag to block entry. Use entry-group to determine who this affects.
* Added exit region flag to block exit. Use exit-group to determine who this affects.
* Made negative healing possible via the healing flag.
* Changed the configuration header messages to be more helpful to new users.
* Added a warning about modifying region files by hand.
* Improved the API for plugin developers.
## 5.1
* A lot of changes.
## 4.0-alpha1
* This release is only to fix WorldGuard for Bukkit. Ignore the 4.0 label. Just move along. Nothing to see.
## 3.2.2
* Changed disable-water-damage to disable-drowning-damage.
* Fixed suffocation disable option.
* Fixed fire spread blocking.
* stopfire and allowfire now work in server console, just like in hMod.
## 3.2.1
* Updated for recent Bukkit ItemStack change.
## 3.2
* Added regions.default.pvp to control default PvP setting.
* Updated WorldGuard for the newer builds of Bukkit.
* Fixed creeper explosion blocking.
* Added redstone support to sponges, removed classic water.
* Fixed item durability disable for hoes.
## 3.1.2
* Increased the priority of WorldGuard's event handling.
## 3.1.1
* Fixed creeper and chest flag conflicting.
## 3.1
* Added ability to disable chest protection. New configuration setting (regions.build.chest-access) and new chest flag.
* Possibly fixed projectile blocking in no-PvP zones.
* Added /regionmembership permission that lets people only change the owners and members of regions they own.
## 3.0b2
* Fixed issue where built-in permissions were not (re)loaded.
* Fixed /god not working for others.
## 3.0b1
* Added parent-child relationships to regions.
* Added global build flag.
* Improved flag support.
* Fixed no-PvP zone messages being sent to the wrong person.
* Fixed commands so that they work in a recent version of Bukkit.
* Fixed NullPointerException in explode hook.
## 2.3.1
* Fixed various cast exceptions with the blacklist loggers.
* Added checks for unchecked exceptions when resolving permissions.
* Fixed the item durability disable setting changing the damage value on an empty hand.
## 2.3
* /god now works very well.
* Item (TNT, flint and steel, etc.) blocking should now work.
* The TNT blocking configuration variable should now work.
* Re-added /heal (not sure where that went), added /slay.
* Implemented contact damage disable toggle.
* Made all player damage disabling configuration parameters work.
* Fixed teleport-on-suffocation setting.
* Added /locate <name>, /locate <x> <y> <z>, and /locate that lets you program/change your compass bearing to point to a player's position (not yet live), a position, or back to spawn.
* Fixed CSVDatabase spitting an error if the owners list was empty.
## 2.2
* Now supports GroupUsers.
* Added support for blocking creeper explosions.
* Fixed a bug where a player's groups were not being loaded correctly, causing the blacklist group ignore option to not work.
## 2.1.1
* Fixed fire spread disable preventing flint and steel too.
* Fixed NullPointerException related to the player item event.
* Made setup simpler.
## 2.1
* Improved Bukkit support.
## 2.0beta3
* Fixed NullPointerException inside the ignite hook.
## 2.0beta2
* Fixed a NullPointerException in the damage hook.
## 2.0beta1
* Added area protection. Use /region or /rg to define regions.
## 1.8.1
* Fixed NullPointerException.
## 1.8
* Updated for Minecraft beta.
* Blacklist hooks have CHANGED. The new hooks are work better. on-create has been replaced with on-place (for block placement) and on-use (for item usage, light buckets and lighters). The old on-use is now on-right-click although it currently does nothing.
* Added coordinates to blacklist file logger.
* Added suffocation damage prevention.
## 1.7.1
* Updated for v0.2.8.
## 1.7
* Updated for v0.2.6_02 and hMod b129.
* Added option to prevent water from damaging particular blocks (Redstone wire, Minecart tracks, etc.). See disable-water-damage-blocks.
* /reload WorldGuard should now reload WorldGuard's configuration.
* Added wg-invincible and wg-amphibious groups that let you give certain players invincibility or underwater breathing.
* Added the ability to disable fall, water, lava, and/or fire damage.
* Water/lava bucket blocking should now be more reliable.
* Added /stack (alias /;) commands to stack items in your inventory into piles up to 64 items in size. Even unstackable items like signs can be stacked.
* /god mode should now let you gain health.
* /god mode should now work more reliably.
* Caught an error message for when the configuration file does not exist.
## 1.6
* Added spawn protection that prevents damage when a player spawns.
* Added login protection that prevents damage when a player joins.
* Added /god. /god can be used on others, provided that the /godother permission is set for the command's user.
## 1.5.1
* Removed the 'java.lang.NoSuchMethodError: Item.setDamage(I)V' error generated.
## 1.5
* Removed the block lag fix.
* WorldGuard now conditionally loads features so you can use any up-to-date build of hMod and the unsupported features won't break the entire plugin. When WG loads, check the server console for a report of features that are not supported by your version of hMod.
* Changed some configuration defaults: disable-lava-fire=true simulate-sponge=true item-durability=false
## 1.4.1
* Fixed issue with the block lag fix dropping item stacks of 0 quantity.
## 1.4
* New on-acquire hook. This does both a total inventory check on inventory change and item pick up denial. The item pick up denial is largely thanks to Dinnerbone for fulfilling my request to add a particular hook.
* Item durability can now be toggled with item-durability. Thanks to Dinnerbone for figuring this out while filfilling my request. The default setting is to fix item durability.
* New no-physics-gravel and no-physics-sand options allow you to prevent gravel and sand from falling.
* New allow-portal-anywhere option allows you to create portal blocks anywhere.
## 1.3
* UPGRADE WARNING: If you are using database logging, you must add a NULL 'comment' VARCHAR field to the table. The line of SQL that you can run for MySQL can be found in blacklist_table.sql.
* Improved plugin compatibility with the block lag fix. For maximum compatibility, you must now list WorldGuard as the first plugin in server.properties and you cannot reload or enable the plugin while the server is up. This is for bad plugins that unnecessarily use the "critical" priority for its hooks like the LWC. Most plugins don't do that though, so this won't apply for most people.
* Fixed signs being blank if they were denied via the blacklist.
* Added on-break event to the blacklist.
* Added comments and messages. Comments are only for your own use and they are printed with the log and notify actions of the blacklist. The message replaces the message that is shown the user and it is optional.
* The blacklist notification messages are now more compact and are light grey instead of light purple.
* The notify, log, and tell actions will now trigger every time for the on-break, on-create, on-drop events rather than wait 3 seconds between events for the same item or block for a player.
## 1.2
* /stopfire and /allowfire disable and enable fire spreading globally.
* Block lag fix slightly improved in accuracy for item drops.
* Sponge updated to remove water when the sponge block is set. Sponge radius can now be controlled using the 'sponge-radius' parameter and the default is now set to simulate Classic.
* Updated for a newer build of "b126," meaning that lava spread control now works well!
* A new summary of the status of some core protections is now printed on start. Disable this with 'summary-on-start'.
* Blacklist system has been overhauled. Check README.txt for changed configuration settings!
* The blacklist's method of preventing notification repeats is now better, instead waiting 3 seconds before notifying again (before it didn't notify again at all unless the user started using another blocked action).
* To give users the ability to receive notifications, the command to give permission to has been changed to /worldguardnotify, although the old one (that was never mentioned anywhere) still works.
* Water and lava buckets are now psuedo-blocked using an unreliable method that risks the stability of your server (no other plugin does it better though). Use it as your own risk.
* Added on item drop and on item use (i.e. chest) events.
* Chests, signs, and furnaces can now be blocked better with the blacklist system.
* The event names in the blacklist configuration have changed but the old event names should still work. The new names should make "more sense."
* A new "ban" action has been added to the blacklist.
* Action messages have been improved, now longer saying "destroyed" for everything.
* Logging to file has been completely changed, allowing you to use the date and time and the player's username in the log filename. It no longer rotates log files based on size, however.
* Logging to database is now supported.
* Tools can now be destroyed on drop to alleviate the durability cheat. You can do this with either with the blacklist or with the 'item-drop-blacklist' configuration option. The configuration option prints more friendly messages than the 'tell' action of blacklists.
## 1.1.2
* Block lag fix: Snow and glass should no longer drop items.
* Block lag fix: Block object now reset after hook call.
## 1.1.1
* Fixed redstone wire dropping wood blocks with the block lag fix.
* The block lag fix now consults other plugins so that ALL protection mechanisms and plugins should work.
## 1.1
* Added block lag fix.
## 1.0
* Initial release.
+459
View File
@@ -0,0 +1,459 @@
5.6:
- Added official support for Minecraft 1.4. Support for 1.3.2 (and below) is still
provided in this release.
- Added support for new and existing explosion types.
- Added support for blocking withers with the following settings:
mobs:
block-wither-explosions: false
block-wither-block-damage: false
block-wither-skull-explosions: false
block-wither-skull-block-damage: true
- Added support for blocking item frames (and their use) in protected regions.
- Added item frame destruction region flags (if you wish to disable item frame
destruction completely).
- (Re-)added support for priority R-tree region indexes. This means quicker region lookup,
and better support for servers with thousands of regions.
- Improved /region info output for -g group flags.
- Allowed removing of -g group flags with /region flag.
- Allowed /region flag to set group and value at once.
- Deleting a region flag now also deletes group flag.
- Fixed detection of attack by projectiles to be more accurate.
- Fixed support for saving non-string flags in the MySQL region support.
- Fixed spurious comma in "Flags:" /region info output.
- Fixed players who are not in god mode not receiving damage in PVP areas from
enderpearls.
- Players will now be told that they are in a no-PvP area if they are in one and
attempting to attack someone, or that the player they are attacking is in a
no-PvP area, if that is the case instead.
- Fixed an issue where region.getId() was lowercase'd each pass of a for loop in
MySQLDatabase.updatePoly2dPoints().
- Fixed mob damage from projectiles not being properly blocked in regions where
applicable.
- Changed default region wand to leather (#334).
Thank you to the following individuals for their contribution:
thvortex, Rutr, Glitchfinder, and DarthAndroid.
5.5.4:
- Minecraft 1.3 support.
- Fixed /stack dupe bugs.
- Added regions.use-creature-spawn-event.
- Update for Async chat issue.
- Add use flag to cakes.
- Report number of plugins loaded in report writer.
- Updated fireblal item blocking.
- Fixed permissions for /region reload.
5.5.3:
- Added game mode flag.
- Added item drop pickup flag to regions.
- Added support for fireball item blocking (385).
- Added configuration option to allow creature spawns from plugins.
- Added host key check.
- Added a new line split feature to region greetings.
- Prevented commands in the allow commands list from being blocked and
vice versa.
5.5.2:
- Added potion-splash flag to block splash potions
- Add entity-painting-destroy which can be used to prevent entities from destroying
paintings (skeletons firing arrows)
- Added send-chat and receive-chat flags
- Fixed having regions in multiple worlds with the same name not working with MySQL
- A cancellable event is now fired if WorldGuard disallows PvP. (for developers!)
- Made /region setparent check worldguard.region.setparent.own/member.<parent> instead
of worldguard.region.setparent.own/member.<child>.
- Allowed passing #<index> in place of a region ID, where <index> is the index as
displayed by /region list.
- Fixed an error that occured when clearing a non-existant region's parent.
- Added a -s flag to /region teleport, which sends you to the spawn point instead of the
teleport point of a region.
- Added region/role-based permissions to /region teleport.
- BREAKING CHANGE: Added a LocationFlag class and made the teleport and spawn flags
use it.
- /region info -s now selects the region being queried.
- Added /region teleport <id>.
- Vector flags can now be set to the current location with the value "here" and to a
specific position with x,y,z.
- Made /region info show the region you're in if you don't specify an id explicitly.
- Prevent block ignition from lightning strikes if lightning is blocked in region. Fixes
#1175
- Correctly check both WEPIF and superperms in WorldGurdPlugin.broadcastNotification()
- Destroy fire blocks when fire-spread is disallowed
- Added a construct flag that can be used to restrict block placing/destroying in zones
to certain roles.
- Added FallingSand to list of intensive entities to be removed with /halt-activiy.
- Replaced all usage of CreatureType by EntityType.
- Updated to support Bukkit 1.2-R0.3 and newer
- Made auto-god-mode disabled by default again.
- Added sign protection check disable.
- Cleaned up javadoc, deprecated duplicate methods, other cleanup
- Added a RegionGroupFlag to evey region flag Using the /region flag command with -g,
the region group that the region flag applies to can be set.
5.5.1:
- Fixed attacking with arrows from non-PVP to PVP areas
- Compatibility with Bukkit 1.1-R5
- Removed broken suppress-tick-sync-warnings config option. See bukkit.yml's setings.warn-on-overload option instead.
- Add region and 'can build' information to CommandBook's /whois
Contributions thanks to: NolanSyKinsley
5.5:
- Removed WorldEdit.jar from the classpath to stop conflicts with Bukkit's plugin loader
- Now using Bukkit's tagged logging
- Updated to new event system
- Flush player flag state cache on world change
- Improved compatibility with versions of CommandBook without GodComponent and updated pom dep for 2.0
- Added MySQL region storage method.
- Made explosions display their animations even when the event was blocked.
- Added fallback support for those who don't have a version of CommandBook with GodComponent
- Added LIGHTNING flag to DefaultFlag's flagsList Fixes #1026
- Removed /god, /heal, /locate, and /stack from WorldGuard to CommandBook. CommandBook is now checked to see whether a player is godded.
- Removed remaining usages of org.bukkit.util.config.Configuration
- Removed some unused configuration options
- Added permission worldguard.region.wand to the region wand
- Fixed ProtectedRegion.compareTo.
- Fixed FlatRegionManager.getApplicableRegions to return parent regions as well.
- Added exp-drops flag to disable experience drops per-region.
- Fixed some warnings.
- Updated dependency version for WorldGuard from 5.0 to 5.1-SNAPSHOT.
- Added support for fireballs shot by players being blocked by the PVP flag.
- Now using dynamic command registration
- Split off ender dragon block damage from creeper block damage.
Contributions thanks to: narthollis, DarkArc, Wolvereness, and skeight
5.4:
- Fixed configuration generation on Windows
- Fixed intersection calculation for regions
- Fixed timer and feeding delay for food flags
- Fixed region managers not being created properly (This caused errors related to CREATURE_SPAWN)
- Added support for Minecraft 1.0.1 blocks
- Added support for enchantments and tool damage (worldguard.stack.damaged is the node) with /stack
- Made being in the wg-invincible group respect the configuration's auto-invincible setting
- Added per-group region claim limit maximum
- Added worldguard.region.addowner.unclaimed.* permission for non-economy region 'buying'
- Checking allowed/blocked commands now occurs earlier to override more plugins
- Made PVP flag check whether either player is in a pvp deny region for blocking
Contributions thanks to: epuidokas, wizjany, Turtle9598, and DerFlash
5.3:
- Added new config options and flags to better handle explosions of all types
- Added config options and flags for snow, ice, mushroom spread, grass spread,
and leaf decay
- Added min and max health flags to clamp the values for the existing healing
flags
- Added hunger flags similar to the existing healing flags
- Added an option to disable the use of the move event. This can boost
performance on large servers but will disable the greeting/farewell
and entry/exit flags
- Added flag to prevent pistons (including those that are outside the
region, but would affect blocks inside the region)
- Added a /wg flushstates [player] command to free players stuck in a
region that was exit-deny but no longer exists or the flag was removed
- Added a config option to disable xp orb dropping
- Added config option to disable redstone wire obsidian generators
- Added a vehicle-destroy flag
- Added enderman protection config and flag
- Allowed and blocked command flags will now fall back to the global region
- The worldguard.region.flag.own/member permissions are now
worldguard.region.flag.regions.own/member! Please change your permissions
accordingly.
- Made //stack respect max stack sizes unless the player has the
worldguard.stack.illegitimate permission
- Setting invincibility flag to deny will override god mode unless the player
has worldguard.god.override-regions
- The sleep flag will now prevent beds in the nether from
exploding if set to deny
- Existing regions can no longer be accidentally overwritten.
Use /region redefine to move an existing region.
- The info command will now sort players alphabetically
- Priming TNT by punching it with flint and steal should throw a blacklist
event (consistent with old Minecraft versions)
- The /stoplag command will now remove xp orbs
- Permissions system will use per-world permissions if the provider supports it
- Players in vehicles are now subject to entry/exit and greeting/farewell flags
- Fixed interact blacklist event not logging correctly
- Fixed heal flag taking effect half a block northeast of the region
- Fixed a infinite sign dropping bug
- Fixed players being able to douse fire by punching it in regions they
couldn't build it
- Fixed players being able to eat protected cake
- Fence gate usage can be blocked with the use flag
- Fixed chests being unprotected when they should be in 1.8
- Fixed weather config settings not applying when a world was loaded
- Fixed explosion handling in certain cases
- Fixed arrows working in non-pvp zones
- Fixed buckets working on the border of protected regions in certain cases
Contributions thanks to:
wizjany, zml2008, imjake9, Droolio, epuidokas,
EduardBaer, TomyLobo, and halvors
5.2.2:
- Changed configuration saving so empty lists will be added to
the configuration files.
5.2.1:
- Add region bounds to /region info
- Added the ability to add owners/members to the global region for
handling guest groups. Now if there's owners or members on the global
region, then those that are not on the list cannot build.
- Fixed some flag algorithm issues.
- API: Fixed DefaultDomain.size() not counting players.
- API: Undeprecated ApplicableRegionSet.allows(StateFlag).
5.2:
- Gave the ability to use color colors and macros in greeting
and farewell messages.
- Added disable-ice-melting, disable-snow-formation, disable-mushroom-spread,
disable-snow-melting, disable-ice-formation.
- Added paintings to blacklist support.
- Added default.disable-health-regain.
- Added auto-invincible-permission setting, which lets you use the permission
'worldguard.auto-invincible' to become invincible on join automatically.
- Flames won't appear if you are /god'ed now.
- Added blocked-cmds region flag to block commands.
- Added allowed-cmds region flag to whitelist commands.
- Added entry region flag to block entry. Use entry-group to determine who
this affects.
- Added exit region flag to block exit. Use exit-group to determine who
this affects.
- Made negative healing possible via the healing flag.
- Changed the configuration header messages to be more helpful to new users.
- Added a warning about modifying region files by hand.
- Improved the API for plugin developers.
5.1:
- A lot of changes.
4.0-alpha1:
- This release is only to fix WorldGuard for Bukkit. Ignore the 4.0
label. Just move along. Nothing to see.
3.2.2:
- Changed disable-water-damage to disable-drowning-damage.
- Fixed suffocation disable option.
- Fixed fire spread blocking.
- stopfire and allowfire now work in server console, just like in hMod.
3.2.1:
- Updated for recent Bukkit ItemStack change.
3.2:
- Added regions.default.pvp to control default PvP setting.
- Updated WorldGuard for the newer builds of Bukkit.
- Fixed creeper explosion blocking.
- Added redstone support to sponges, removed classic water.
- Fixed item durability disable for hoes.
3.1.2:
- Increased the priority of WorldGuard's event handling.
3.1.1:
- Fixed creeper and chest flag conflicting.
3.1:
- Added ability to disable chest protection. New configuration setting
(regions.build.chest-access) and new chest flag.
- Possibly fixed projectile blocking in no-PvP zones.
- Added /regionmembership permission that lets people only change
the owners and members of regions they own.
3.0b2:
- Fixed issue where built-in permissions were not (re)loaded.
- Fixed /god not working for others.
3.0b1:
- Added parent-child relationships to regions.
- Added global build flag.
- Improved flag support.
- Fixed no-PvP zone messages being sent to the wrong person.
- Fixed commands so that they work in a recent version of Bukkit.
- Fixed NullPointerException in explode hook.
2.3.1:
- Fixed various cast exceptions with the blacklist loggers.
- Added checks for unchecked exceptions when resolving permissions.
- Fixed the item durability disable setting changing the damage value on
an empty hand.
2.3:
- /god now works very well.
- Item (TNT, flint and steel, etc.) blocking should now work.
- The TNT blocking configuration variable should now work.
- Re-added /heal (not sure where that went), added /slay.
- Implemented contact damage disable toggle.
- Made all player damage disabling configuration parameters work.
- Fixed teleport-on-suffocation setting.
- Added /locate <name>, /locate <x> <y> <z>, and /locate that lets you
program/change your compass bearing to point to a player's position
(not yet live), a position, or back to spawn.
- Fixed CSVDatabase spitting an error if the owners list was empty.
2.2:
- Now supports GroupUsers.
- Added support for blocking creeper explosions.
- Fixed a bug where a player's groups were not being loaded correctly,
causing the blacklist group ignore option to not work.
2.1.1:
- Fixed fire spread disable preventing flint and steel too.
- Fixed NullPointerException related to the player item event.
- Made setup simpler.
2.1:
- Improved Bukkit support.
2.0beta3:
- Fixed NullPointerException inside the ignite hook.
2.0beta2:
- Fixed a NullPointerException in the damage hook.
2.0beta1:
- Added area protection. Use /region or /rg to define regions.
1.8.1
- Fixed NullPointerException.
1.8
- Updated for Minecraft beta.
- Blacklist hooks have CHANGED. The new hooks are work better. on-create has
been replaced with on-place (for block placement) and on-use
(for item usage, light buckets and lighters). The old on-use is now
on-right-click although it currently does nothing.
- Added coordinates to blacklist file logger.
- Added suffocation damage prevention.
1.7.1
- Updated for v0.2.8.
1.7
- Updated for v0.2.6_02 and hMod b129.
- Added option to prevent water from damaging particular blocks
(Redstone wire, Minecart tracks, etc.). See disable-water-damage-blocks.
- /reload WorldGuard should now reload WorldGuard's configuration.
- Added wg-invincible and wg-amphibious groups that let you give certain
players invincibility or underwater breathing.
- Added the ability to disable fall, water, lava, and/or fire damage.
- Water/lava bucket blocking should now be more reliable.
- Added /stack (alias /;) commands to stack items in your inventory into
piles up to 64 items in size. Even unstackable items like signs can be
stacked.
- /god mode should now let you gain health.
- /god mode should now work more reliably.
- Caught an error message for when the configuration file does not exist.
1.6
- Added spawn protection that prevents damage when a player spawns.
- Added login protection that prevents damage when a player joins.
- Added /god. /god can be used on others, provided that the /godother
permission is set for the command's user.
1.5.1
- Removed the 'java.lang.NoSuchMethodError: Item.setDamage(I)V' error
generated.
1.5
- Removed the block lag fix.
- WorldGuard now conditionally loads features so you can use any up-to-date
build of hMod and the unsupported features won't break the entire
plugin. When WG loads, check the server console for a report of
features that are not supported by your version of hMod.
- Changed some configuration defaults:
disable-lava-fire=true
simulate-sponge=true
item-durability=false
1.4.1
- Fixed issue with the block lag fix dropping item stacks of 0 quantity.
1.4
- New on-acquire hook. This does both a total inventory check on inventory
change and item pick up denial. The item pick up denial is largely
thanks to Dinnerbone for fulfilling my request to add a particular hook.
- Item durability can now be toggled with item-durability. Thanks to
Dinnerbone for figuring this out while filfilling my request. The
default setting is to fix item durability.
- New no-physics-gravel and no-physics-sand options allow you to
prevent gravel and sand from falling.
- New allow-portal-anywhere option allows you to create portal blocks
anywhere.
1.3
- UPGRADE WARNING: If you are using database logging, you must add a
NULL 'comment' VARCHAR field to the table. The line of SQL that you
can run for MySQL can be found in blacklist_table.sql.
- Improved plugin compatibility with the block lag fix. For maximum
compatibility, you must now list WorldGuard as the first plugin in
server.properties and you cannot reload or enable the plugin
while the server is up. This is for bad plugins that unnecessarily
use the "critical" priority for its hooks like the LWC. Most plugins
don't do that though, so this won't apply for most people.
- Fixed signs being blank if they were denied via the blacklist.
- Added on-break event to the blacklist.
- Added comments and messages. Comments are only for your own use and they
are printed with the log and notify actions of the blacklist. The
message replaces the message that is shown the user and it is optional.
- The blacklist notification messages are now more compact and are
light grey instead of light purple.
- The notify, log, and tell actions will now trigger every time for the
on-break, on-create, on-drop events rather than wait 3 seconds between
events for the same item or block for a player.
1.2
- /stopfire and /allowfire disable and enable fire spreading globally.
- Block lag fix slightly improved in accuracy for item drops.
- Sponge updated to remove water when the sponge block is set. Sponge radius
can now be controlled using the 'sponge-radius' parameter and the
default is now set to simulate Classic.
- Updated for a newer build of "b126," meaning that lava spread control
now works well!
- A new summary of the status of some core protections is now printed
on start. Disable this with 'summary-on-start'.
- Blacklist system has been overhauled. Check README.txt for changed
configuration settings!
- The blacklist's method of preventing notification repeats is now better,
instead waiting 3 seconds before notifying again (before it didn't
notify again at all unless the user started using another blocked
action).
- To give users the ability to receive notifications, the command to give
permission to has been changed to /worldguardnotify, although the
old one (that was never mentioned anywhere) still works.
- Water and lava buckets are now psuedo-blocked using an unreliable
method that risks the stability of your server (no other plugin
does it better though). Use it as your own risk.
- Added on item drop and on item use (i.e. chest) events.
- Chests, signs, and furnaces can now be blocked better with the
blacklist system.
- The event names in the blacklist configuration have changed but the old
event names should still work. The new names should make "more sense."
- A new "ban" action has been added to the blacklist.
- Action messages have been improved, now longer saying "destroyed"
for everything.
- Logging to file has been completely changed, allowing you to use
the date and time and the player's username in the log filename. It
no longer rotates log files based on size, however.
- Logging to database is now supported.
- Tools can now be destroyed on drop to alleviate the durability cheat.
You can do this with either with the blacklist or with the
'item-drop-blacklist' configuration option. The configuration option
prints more friendly messages than the 'tell' action of blacklists.
1.1.2
- Block lag fix: Snow and glass should no longer drop items.
- Block lag fix: Block object now reset after hook call.
1.1.1
- Fixed redstone wire dropping wood blocks with the block lag fix.
- The block lag fix now consults other plugins so that ALL protection
mechanisms and plugins should work.
1.1
- Added block lag fix.
1.0
- Initial release.
+3 -2
View File
@@ -1,10 +1,11 @@
# Contributing
Contributing
============
Thank you for your interest in contributing to WorldGuard! We appreciate your
effort, but to make sure that the inclusion of your patch is a smooth process, we
ask that you make note of the following guidelines.
* **Follow the [Oracle coding conventions](https://www.oracle.com/technetwork/java/javase/documentation/codeconvtoc-136057.html).**
* **Follow the [Oracle coding conventions](http://www.oracle.com/technetwork/java/codeconv-138413.html).**
We can't stress this enough; if your code has notable issues, it may delay
the process significantly.
* **Target Java 6 for source and compilation.** Make sure to mark methods with
-16
View File
@@ -1,16 +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/>.
+202 -200
View File
@@ -1,201 +1,203 @@
GNU LESSER GENERAL PUBLIC LICENSE
Version 3, 29 June 2007
Copyright (C) 2007 Free Software Foundation, Inc. <http://fsf.org/>
Everyone is permitted to copy and distribute verbatim copies
of this license document, but changing it is not allowed.
This version of the GNU Lesser General Public License incorporates
the terms and conditions of version 3 of the GNU General Public
License, supplemented by the additional permissions listed below.
0. Additional Definitions.
As used herein, "this License" refers to version 3 of the GNU Lesser
General Public License, and the "GNU GPL" refers to version 3 of the GNU
General Public License.
"The Library" refers to a covered work governed by this License,
other than an Application or a Combined Work as defined below.
An "Application" is any work that makes use of an interface provided
by the Library, but which is not otherwise based on the Library.
Defining a subclass of a class defined by the Library is deemed a mode
of using an interface provided by the Library.
A "Combined Work" is a work produced by combining or linking an
Application with the Library. The particular version of the Library
with which the Combined Work was made is also called the "Linked
Version".
The "Minimal Corresponding Source" for a Combined Work means the
Corresponding Source for the Combined Work, excluding any source code
for portions of the Combined Work that, considered in isolation, are
based on the Application, and not on the Linked Version.
The "Corresponding Application Code" for a Combined Work means the
object code and/or source code for the Application, including any data
and utility programs needed for reproducing the Combined Work from the
Application, but excluding the System Libraries of the Combined Work.
1. Exception to Section 3 of the GNU GPL.
You may convey a covered work under sections 3 and 4 of this License
without being bound by section 3 of the GNU GPL.
2. Conveying Modified Versions.
If you modify a copy of the Library, and, in your modifications, a
facility refers to a function or data to be supplied by an Application
that uses the facility (other than as an argument passed when the
facility is invoked), then you may convey a copy of the modified
version:
a) under this License, provided that you make a good faith effort to
ensure that, in the event an Application does not supply the
function or data, the facility still operates, and performs
whatever part of its purpose remains meaningful, or
b) under the GNU GPL, with none of the additional permissions of
this License applicable to that copy.
3. Object Code Incorporating Material from Library Header Files.
The object code form of an Application may incorporate material from
a header file that is part of the Library. You may convey such object
code under terms of your choice, provided that, if the incorporated
material is not limited to numerical parameters, data structure
layouts and accessors, or small macros, inline functions and templates
(ten or fewer lines in length), you do both of the following:
a) Give prominent notice with each copy of the object code that the
Library is used in it and that the Library and its use are
covered by this License.
b) Accompany the object code with a copy of the GNU GPL and this license
document.
4. Combined Works.
You may convey a Combined Work under terms of your choice that,
taken together, effectively do not restrict modification of the
portions of the Library contained in the Combined Work and reverse
engineering for debugging such modifications, if you also do each of
the following:
a) Give prominent notice with each copy of the Combined Work that
the Library is used in it and that the Library and its use are
covered by this License.
b) Accompany the Combined Work with a copy of the GNU GPL and this license
document.
c) For a Combined Work that displays copyright notices during
execution, include the copyright notice for the Library among
these notices, as well as a reference directing the user to the
copies of the GNU GPL and this license document.
d) Do one of the following:
0) Convey the Minimal Corresponding Source under the terms of this
License, and the Corresponding Application Code in a form
suitable for, and under terms that permit, the user to
recombine or relink the Application with a modified version of
the Linked Version to produce a modified Combined Work, in the
manner specified by section 6 of the GNU GPL for conveying
Corresponding Source.
1) Use a suitable shared library mechanism for linking with the
Library. A suitable mechanism is one that (a) uses at run time
a copy of the Library already present on the user's computer
system, and (b) will operate properly with a modified version
of the Library that is interface-compatible with the Linked
Version.
e) Provide Installation Information, but only if you would otherwise
be required to provide such information under section 6 of the
GNU GPL, and only to the extent that such information is
necessary to install and execute a modified version of the
Combined Work produced by recombining or relinking the
Application with a modified version of the Linked Version. (If
you use option 4d0, the Installation Information must accompany
the Minimal Corresponding Source and Corresponding Application
Code. If you use option 4d1, you must provide the Installation
Information in the manner specified by section 6 of the GNU GPL
for conveying Corresponding Source.)
5. Combined Libraries.
You may place library facilities that are a work based on the
Library side by side in a single library together with other library
facilities that are not Applications and are not covered by this
License, and convey such a combined library under terms of your
choice, if you do both of the following:
a) Accompany the combined library with a copy of the same work based
on the Library, uncombined with any other library facilities,
conveyed under the terms of this License.
b) Give prominent notice with the combined library that part of it
is a work based on the Library, and explaining where to find the
accompanying uncombined form of the same work.
6. Revised Versions of the GNU Lesser General Public License.
The Free Software Foundation may publish revised and/or new versions
of the GNU Lesser General Public License from time to time. Such new
versions will be similar in spirit to the present version, but may
differ in detail to address new problems or concerns.
Each version is given a distinguishing version number. If the
Library as you received it specifies that a certain numbered version
of the GNU Lesser General Public License "or any later version"
applies to it, you have the option of following the terms and
conditions either of that published version or of any later version
published by the Free Software Foundation. If the Library as you
received it does not specify a version number of the GNU Lesser
General Public License, you may choose any version of the GNU Lesser
General Public License ever published by the Free Software Foundation.
If the Library as you received it specifies that a proxy can decide
whether future versions of the GNU Lesser General Public License shall
apply, that proxy's public statement of acceptance of any version is
permanent authorization for you to choose that version for the
Library.
----------------------------------------------------------------------------
This work includes Robert Olofsson's Priority R-Tree implementation, for which
its license is reproduced below.
Copyright (c) 2008-2010 Robert Olofsson.
All rights reserved.
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions
are met:
1. Redistributions of source code must retain the above copyright
notice, this list of conditions and the following disclaimer.
2. Redistributions in binary form must reproduce the above copyright
notice, this list of conditions and the following disclaimer in the
documentation and/or other materials provided with the distribution.
3. Neither the name of the authors nor the names of its contributors
may be used to endorse or promote products derived from this software
without specific prior written permission.
THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE
FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
----------------------------------------------------------------------------
WorldGuard License
----------------------------------------------------------------------------
GNU LESSER GENERAL PUBLIC LICENSE
Version 3, 29 June 2007
Copyright (C) 2007 Free Software Foundation, Inc. <http://fsf.org/>
Everyone is permitted to copy and distribute verbatim copies
of this license document, but changing it is not allowed.
This version of the GNU Lesser General Public License incorporates
the terms and conditions of version 3 of the GNU General Public
License, supplemented by the additional permissions listed below.
0. Additional Definitions.
As used herein, "this License" refers to version 3 of the GNU Lesser
General Public License, and the "GNU GPL" refers to version 3 of the GNU
General Public License.
"The Library" refers to a covered work governed by this License,
other than an Application or a Combined Work as defined below.
An "Application" is any work that makes use of an interface provided
by the Library, but which is not otherwise based on the Library.
Defining a subclass of a class defined by the Library is deemed a mode
of using an interface provided by the Library.
A "Combined Work" is a work produced by combining or linking an
Application with the Library. The particular version of the Library
with which the Combined Work was made is also called the "Linked
Version".
The "Minimal Corresponding Source" for a Combined Work means the
Corresponding Source for the Combined Work, excluding any source code
for portions of the Combined Work that, considered in isolation, are
based on the Application, and not on the Linked Version.
The "Corresponding Application Code" for a Combined Work means the
object code and/or source code for the Application, including any data
and utility programs needed for reproducing the Combined Work from the
Application, but excluding the System Libraries of the Combined Work.
1. Exception to Section 3 of the GNU GPL.
You may convey a covered work under sections 3 and 4 of this License
without being bound by section 3 of the GNU GPL.
2. Conveying Modified Versions.
If you modify a copy of the Library, and, in your modifications, a
facility refers to a function or data to be supplied by an Application
that uses the facility (other than as an argument passed when the
facility is invoked), then you may convey a copy of the modified
version:
a) under this License, provided that you make a good faith effort to
ensure that, in the event an Application does not supply the
function or data, the facility still operates, and performs
whatever part of its purpose remains meaningful, or
b) under the GNU GPL, with none of the additional permissions of
this License applicable to that copy.
3. Object Code Incorporating Material from Library Header Files.
The object code form of an Application may incorporate material from
a header file that is part of the Library. You may convey such object
code under terms of your choice, provided that, if the incorporated
material is not limited to numerical parameters, data structure
layouts and accessors, or small macros, inline functions and templates
(ten or fewer lines in length), you do both of the following:
a) Give prominent notice with each copy of the object code that the
Library is used in it and that the Library and its use are
covered by this License.
b) Accompany the object code with a copy of the GNU GPL and this license
document.
4. Combined Works.
You may convey a Combined Work under terms of your choice that,
taken together, effectively do not restrict modification of the
portions of the Library contained in the Combined Work and reverse
engineering for debugging such modifications, if you also do each of
the following:
a) Give prominent notice with each copy of the Combined Work that
the Library is used in it and that the Library and its use are
covered by this License.
b) Accompany the Combined Work with a copy of the GNU GPL and this license
document.
c) For a Combined Work that displays copyright notices during
execution, include the copyright notice for the Library among
these notices, as well as a reference directing the user to the
copies of the GNU GPL and this license document.
d) Do one of the following:
0) Convey the Minimal Corresponding Source under the terms of this
License, and the Corresponding Application Code in a form
suitable for, and under terms that permit, the user to
recombine or relink the Application with a modified version of
the Linked Version to produce a modified Combined Work, in the
manner specified by section 6 of the GNU GPL for conveying
Corresponding Source.
1) Use a suitable shared library mechanism for linking with the
Library. A suitable mechanism is one that (a) uses at run time
a copy of the Library already present on the user's computer
system, and (b) will operate properly with a modified version
of the Library that is interface-compatible with the Linked
Version.
e) Provide Installation Information, but only if you would otherwise
be required to provide such information under section 6 of the
GNU GPL, and only to the extent that such information is
necessary to install and execute a modified version of the
Combined Work produced by recombining or relinking the
Application with a modified version of the Linked Version. (If
you use option 4d0, the Installation Information must accompany
the Minimal Corresponding Source and Corresponding Application
Code. If you use option 4d1, you must provide the Installation
Information in the manner specified by section 6 of the GNU GPL
for conveying Corresponding Source.)
5. Combined Libraries.
You may place library facilities that are a work based on the
Library side by side in a single library together with other library
facilities that are not Applications and are not covered by this
License, and convey such a combined library under terms of your
choice, if you do both of the following:
a) Accompany the combined library with a copy of the same work based
on the Library, uncombined with any other library facilities,
conveyed under the terms of this License.
b) Give prominent notice with the combined library that part of it
is a work based on the Library, and explaining where to find the
accompanying uncombined form of the same work.
6. Revised Versions of the GNU Lesser General Public License.
The Free Software Foundation may publish revised and/or new versions
of the GNU Lesser General Public License from time to time. Such new
versions will be similar in spirit to the present version, but may
differ in detail to address new problems or concerns.
Each version is given a distinguishing version number. If the
Library as you received it specifies that a certain numbered version
of the GNU Lesser General Public License "or any later version"
applies to it, you have the option of following the terms and
conditions either of that published version or of any later version
published by the Free Software Foundation. If the Library as you
received it does not specify a version number of the GNU Lesser
General Public License, you may choose any version of the GNU Lesser
General Public License ever published by the Free Software Foundation.
If the Library as you received it specifies that a proxy can decide
whether future versions of the GNU Lesser General Public License shall
apply, that proxy's public statement of acceptance of any version is
permanent authorization for you to choose that version for the
Library.
----------------------------------------------------------------------------
PRTree License
----------------------------------------------------------------------------
Copyright (c) 2008-2010 Robert Olofsson.
All rights reserved.
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions
are met:
1. Redistributions of source code must retain the above copyright
notice, this list of conditions and the following disclaimer.
2. Redistributions in binary form must reproduce the above copyright
notice, this list of conditions and the following disclaimer in the
documentation and/or other materials provided with the distribution.
3. Neither the name of the authors nor the names of its contributors
may be used to endorse or promote products derived from this software
without specific prior written permission.
THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE
FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
SUCH DAMAGE.
+232
View File
@@ -0,0 +1,232 @@
<!DOCTYPE html>
<html>
<head>
<title>${project.name} ${version}</title>
<link href="http://fonts.googleapis.com/css?family=Source+Sans+Pro:400,700|Ropa+Sans" rel="stylesheet" type="text/css">
<style>
body {
margin: 0;
padding: 3em 1em;
background: #efefef;
color: #333;
line-height: 1.5;
}
#wrapper {
width: 600px;
margin: auto;
}
body, th, td, input {
font: 14px 'Source Sans Pro', Arial, sans-serifsans-serif;
}
.section {
background: #fff;
position: relative;
padding: 2em 2.4em;
margin: 3em auto 4em auto;
width: 80%;
-webkit-box-shadow: 0 1px 4px rgba(0, 0, 0, 0.1);
-moz-box-shadow: 0 1px 4px rgba(0, 0, 0, 0.1);
box-shadow: 0 1px 4px rgba(0, 0, 0, 0.1);
}
.section:before, .section:after {
content: "";
position: absolute;
z-index: -2;
}
.section {
-moz-border-radius: 4px;
border-radius: 4px;
}
.section:before, .section:after {
bottom: 15px;
left: 10px;
width: 50%;
height: 20%;
max-width: 300px;
max-height: 100px;
-webkit-box-shadow: 0 15px 10px rgba(0, 0, 0, 0.5);
-moz-box-shadow: 0 15px 10px rgba(0, 0, 0, 0.5);
box-shadow: 0 15px 10px rgba(0, 0, 0, 0.5);
-webkit-transform: rotate(-1deg);
-moz-transform: rotate(-1deg);
-ms-transform: rotate(-1deg);
-o-transform: rotate(-1deg);
transform: rotate(-1deg);
}
.section:after {
right: 10px;
left: auto;
-webkit-transform: rotate(1deg);
-moz-transform: rotate(1deg);
-ms-transform: rotate(1deg);
-o-transform: rotate(1deg);
transform: rotate(1deg);
}
a:link, a:visited {
color: #0004b2;
text-decoration: none;
}
a:hover {
color: #ac0000;
text-decoration: none;
border-bottom: 1px solid #999;
}
h1 {
font: 2.7em 'Ropa Sans', 'Trebuchet MS', Helvetica, Arial, sans-serif;
color: #000;
margin: 0 0;
padding: 0 0 0.2em 0;
font-weight: normal;
text-align: center;
text-shadow: 2px 2px #FFF;
}
h2 {
font-size: 1.3em;
color: #FFF;
margin: -2.5em 0 0.8em 0;
float: left;
background: #0049FF;
padding: 0.4em 0.8em;
border-radius: 0.2em;
font-weight: normal;
text-align: center;
}
h3 {
text-transform: uppercase;
font-weight: bold;
}
h2 + * {
clear: both;
}
@media (max-width: 650px) {
#wrapper {
width: 100%;
}
}
</style>
</head>
<body>
<div id="wrapper">
<h1>${project.name} ${version}</h1>
<div class="section">
<h2>Getting Started</h2>
<p>
Thanks for choosing ${project.name}! When you first install ${project.name},
nothing will be enabled, so you will need to switch on the features
that you need to use, whenever it is convenient for you.
</p>
<ul>
<li><a href="http://wiki.sk89q.com/wiki/${project.name}/Installation">How do I install ${project.name}?</a></li>
<li><a href="http://wiki.sk89q.com/wiki/${project.name}/Upgrading">How do I update ${project.name}?</a></li>
<li><a href="http://wiki.sk89q.com/wiki/${project.name}#Usage">How do I use ${project.name}?</a></li>
</ul>
<p>
Need help?
<a href="http://wiki.sk89q.com/wiki/${project.name}/Support">See the ways that you can get assistance</a>.
</p>
</div>
<div class="section">
<h2>Common Issues</h2>
<h3>What are the other files that come with the download?</h3>
<p>
Inside the folder "contrib" of the download are the following files:
</p>
<ul>
<li>blacklist_table.sql is for using a database with the
<a href="http://wiki.sk89q.com/wiki/${project.name}/Blacklist">blacklist feature</a>.</li>
<li>region_storage.sql is for using a database with the
<a href="http://wiki.sk89q.com/wiki/${project.name}/Regions">region protection feature</a>.</li>
<li>region_storage_update_20110325.sql is for updating your region protection
database (if you're using it) if your database was made before March 25, 2011.</li>
</ul>
<h3>${project.name} doesn't seem to work.</h3>
<p>
Two common mistakes include forgetting to install WorldEdit
(${project.name} needs it), or making
a syntax error in one of ${project.name}'s configuration files (this is very
fatal unfortunately, and can be caused by a single character typed in the wrong place). Try
<a href="http://wiki.sk89q.com/wiki/${project.name}/Support">asking in IRC</a>
to see whether anyone can help you.
</p>
<h3>How do I protect my spawn, or another area?</h3>
<p>
Read the <a href="http://wiki.sk89q.com/wiki/${project.name}/Regions/Tutorial">area protection tutorial</a>
on our wiki. For more detailed information, be sure to read about
<a href="http://wiki.sk89q.com/wiki/WorldGuard/Regions">region protection on the wiki</a>. Note
that if you can't build in spawn, don't forget that Minecraft comes with its own
limited spawn protection that you have to disable (see below).
</p>
<h3>I or others don't have permission to build.</h3>
<p>
Unless you copied configuration files from an older installation of
${project.name}, your problem is either caused by another plugin, or by not
disabling the built-in spawn protection of the Minecraft server.
</p>
<h3>No one can build in a region I made!</h3>
<p>
Make sure that:
</p>
<ul>
<li>You didn't change the 'build' flag, because protection is on by default
when a new region is made. Setting the build flag to 'deny' means that
no one can modify the things inside the region.</li>
<li>That you added the player as an owner or member of the region. If you are using
a group (g:groupName), you may have to give the group the permission of
group.groupName for ${project.name} to recognize it.</li>
<li>That you disabled spawn protection. The Minecraft server has an automatic
spawn protection feature where only 'ops' can build in a definable
radius around spawn (by default, it is 16 blocks). If you are on Minecraft
1.4 or newer, edit "spawn-protection" in server.properties; otherwise, modify bukkit.yml
and change the spawn-radius setting.</li>
<li>That it's not another plugin causing you trouble. The error messages of ${project.name} are of
a dark red shade. If the color of the "no permission" message is not
that color, it is not ${project.name}.</li>
</ul>
<h3>Everyone can build in a region I made!</h3>
<p>
Make sure that:
</p>
<ul>
<li>You didn't change the 'build' flag, because protection is on by default
when a new region is made. Setting the build flag to 'allow' means that
anyone can modify the things inside the region.</li>
<li>That it's not caused by another plugin. If players are getting a dark red
permission denied message, but they can still build, another plugin
is likely causing the conflict.</li>
</ul>
<h3>Where do I report bugs or suggest ideas?</h3>
<p>
Make sure you are using the latest version of ${project.name}, try asking in
IRC first (see "Need help?" above) if it's a problem, and if you think you've
found a bug or have a great suggestion to provide, please
report it to <a href="http://youtrack.sk89q.com/issues/WORLDGUARD">our issue tracker</a>.
</p>
<p>
Still need help?
<a href="http://wiki.sk89q.com/wiki/${project.name}/Support">See the ways that you can get assistance</a>.
</p>
</div>
<div class="section">
<h2>Contributing</h2>
<p>
Did you know that ${project.name} is open source? That means that you can
read the code and learn from it, as well as modify it and submit back
changes to help the community!
</p>
<ul>
<li><a href="https://github.com/sk89q/worldguard">View the source code</a></li>
<li><a href="http://wiki.sk89q.com/wiki/${project.name}/Development">More information</a></li>
</ul>
</div>
</div>
</body>
</html>
+35 -46
View File
@@ -1,46 +1,35 @@
# ![WorldGuard](worldguard-logo.png)
WorldGuard lets you and players guard areas of land against griefers and undesirables, as well as tweak and disable various gameplay features of Minecraft.
* Block creeper and wither block damage, falling damage, etc.;
* Disable fire spread, lava fire spread, ice formation, Endermen picking up blocks, etc.;
* Blacklist certain items and blocks so they can't be used;
* Warn moderators when certain items and blocks are used;
* Protect areas of your world so only certain people can build in them;
* Set areas where PVP, TNT, mob damage, and other features are disabled;
* Protect your server from various 'exploits' like magical obsidian creation machines;
* Disable, or enable, various Minecraft features, like sponges from classic;
* Add useful commands like an immediate "STOP ALL FIRE SPREAD" command.
* Enable only features you want! Everything is off by default.
WorldGuard is open source and is available under the GNU Lesser
General Public License v3.
Currently, Bukkit is required to use WorldGuard. You can get a release copy of WorldGuard from the [BukkitDev site](http://dev.bukkit.org/bukkit-plugins/worldguard/).
Compiling
---------
The project is written for Java 8 and our build process makes use of
[Gradle](http://gradle.org).
Dependencies are automatically handled by Gradle.
Contributing
------------
We happily accept contributions, especially through pull requests on GitHub.
Please read CONTRIBUTING.md for important guidelines to follow.
Submissions must be licensed under the GNU Lesser General Public License v3.
Links
-----
* [Homepage](http://enginehub.org/worldguard)
* [Discord](https://discord.gg/enginehub)
* [IRC channel](https://webchat.esper.net/?join=sk89q) (#sk89q on irc.esper.net)
* [Issue tracker](https://dev.enginehub.org/issues/WORLDGUARD)
* [Continuous integration](http://builds.enginehub.org) [![Build Status](https://ci.enginehub.org/app/rest/builds/buildType:bt11,branch:master/statusIcon.svg)](http://ci.enginehub.org/viewType.html?buildTypeId=bt11&guest=1)
* [End-user documentation](https://worldguard.enginehub.org/en/latest/)
![WorldGuard](http://static.sk89q.com/readme/worldguard.png)
==========
WorldGuard is a toolbox of various functions, useful for multiplayer servers, that lets you:
* Protect your server from a number of problems.
* Block fire spread, lava spread, endermen, and more.
* Flag areas as "no PVP" or "no TNT."
* Assign ownership to areas so only selected individuals can build.
* Use a number of useful commands.
WorldGuard is open source and is available under the GNU General Public License v3.
Compiling
---------
The project is written for Java 6 and our build process makes use of [Maven](http://maven.apache.org). Detailed compilation information [can be found on the wiki](http://wiki.sk89q.com/wiki/WorldGuard/Development#Compiling).
Dependencies are automatically handled by Maven.
Contributing
------------
We happily accept contributions, especially through pull requests on GitHub. Submissions
must be licensed under the GNU General Public License v3.
Please read CONTRIBUTING.md for important guidelines to follow.
Links
-----
* [IRC channel](http://skq.me/irc/irc.esper.net/sk89q/) (#sk89q on irc.esper.net)
* [Issue tracker](http://youtrack.sk89q.com/issues/WORLDGUARD)
* [Continuous integration](http://build.sk89q.com) [![Build Status](https://secure.travis-ci.org/sk89q/worldguard.png)](http://travis-ci.org/sk89q/worldguard)
* [End-user documentation](http://wiki.sk89q.com/wiki/WorldGuard)
-26
View File
@@ -1,26 +0,0 @@
import org.ajoberstar.grgit.Grgit
logger.lifecycle("""
*******************************************
You are building WorldGuard!
If you encounter trouble:
1) Try running 'build' in a separate Gradle run
2) Use gradlew and not gradle
3) If you still need help, ask on Discord! https://discord.gg/enginehub
Output files will be in [subproject]/build/libs
*******************************************
""")
applyRootArtifactoryConfig()
if (!project.hasProperty("gitCommitHash")) {
apply(plugin = "org.ajoberstar.grgit")
ext["gitCommitHash"] = try {
(ext["grgit"] as Grgit?)?.head()?.abbreviatedId
} catch (e: Exception) {
logger.warn("Error getting commit hash", e)
"no_git_id"
}
}
-19
View File
@@ -1,19 +0,0 @@
plugins {
`kotlin-dsl`
kotlin("jvm") version embeddedKotlinVersion
}
repositories {
jcenter()
gradlePluginPortal()
}
dependencies {
implementation(gradleApi())
implementation("gradle.plugin.net.minecrell:licenser:0.4.1")
implementation("org.ajoberstar.grgit:grgit-gradle:3.1.1")
implementation("com.github.jengelman.gradle.plugins:shadow:5.1.0")
implementation("net.ltgt.apt-eclipse:net.ltgt.apt-eclipse.gradle.plugin:0.21")
implementation("net.ltgt.apt-idea:net.ltgt.apt-idea.gradle.plugin:0.21")
implementation("org.jfrog.buildinfo:build-info-extractor-gradle:4.9.7")
}
@@ -1,40 +0,0 @@
import org.gradle.api.Project
import org.gradle.kotlin.dsl.apply
import org.gradle.kotlin.dsl.configure
import org.gradle.kotlin.dsl.named
import org.jfrog.gradle.plugin.artifactory.dsl.ArtifactoryPluginConvention
import org.jfrog.gradle.plugin.artifactory.task.ArtifactoryTask
private const val ARTIFACTORY_CONTEXT_URL = "artifactory_contextUrl"
private const val ARTIFACTORY_USER = "artifactory_user"
private const val ARTIFACTORY_PASSWORD = "artifactory_password"
fun Project.applyRootArtifactoryConfig() {
if (!project.hasProperty(ARTIFACTORY_CONTEXT_URL)) ext[ARTIFACTORY_CONTEXT_URL] = "http://localhost"
if (!project.hasProperty(ARTIFACTORY_USER)) ext[ARTIFACTORY_USER] = "guest"
if (!project.hasProperty(ARTIFACTORY_PASSWORD)) ext[ARTIFACTORY_PASSWORD] = ""
apply(plugin = "com.jfrog.artifactory")
configure<ArtifactoryPluginConvention> {
setContextUrl("${project.property(ARTIFACTORY_CONTEXT_URL)}")
clientConfig.publisher.run {
repoKey = when {
"${project.version}".contains("SNAPSHOT") -> "libs-snapshot-local"
else -> "libs-release-local"
}
username = "${project.property(ARTIFACTORY_USER)}"
password = "${project.property(ARTIFACTORY_PASSWORD)}"
isMaven = true
isIvy = false
}
}
tasks.named<ArtifactoryTask>("artifactoryPublish") {
isSkip = true
}
}
fun Project.applyCommonArtifactoryConfig() {
val named = tasks.named<ArtifactoryTask>("artifactoryPublish") {
publishConfigs("archives")
}
}
-18
View File
@@ -1,18 +0,0 @@
import org.gradle.api.Project
import org.gradle.kotlin.dsl.repositories
fun Project.applyCommonConfiguration() {
group = rootProject.group
version = rootProject.version
repositories {
mavenCentral()
maven { url = uri("https://maven.sk89q.com/repo/") }
maven { url = uri("https://oss.sonatype.org/content/repositories/snapshots/") }
}
configurations.all {
resolutionStrategy {
cacheChangingModulesFor(5, "minutes")
}
}
}
-12
View File
@@ -1,12 +0,0 @@
import org.gradle.api.Project
import org.gradle.api.plugins.ExtraPropertiesExtension
import org.gradle.api.plugins.JavaPluginConvention
import org.gradle.api.tasks.SourceSetContainer
import org.gradle.kotlin.dsl.getByType
import org.gradle.kotlin.dsl.the
val Project.ext: ExtraPropertiesExtension
get() = extensions.getByType()
val Project.sourceSets: SourceSetContainer
get() = the<JavaPluginConvention>().sourceSets
-96
View File
@@ -1,96 +0,0 @@
import com.github.jengelman.gradle.plugins.shadow.tasks.ShadowJar
import org.gradle.api.Project
import org.gradle.api.artifacts.ModuleDependency
import org.gradle.api.internal.HasConvention
import org.gradle.api.plugins.MavenRepositoryHandlerConvention
import org.gradle.api.tasks.Upload
import org.gradle.api.tasks.bundling.Jar
import org.gradle.kotlin.dsl.apply
import org.gradle.kotlin.dsl.get
import org.gradle.kotlin.dsl.getPlugin
import org.gradle.kotlin.dsl.invoke
import org.gradle.kotlin.dsl.register
fun Project.applyLibrariesConfiguration() {
applyCommonConfiguration()
apply(plugin = "java-base")
apply(plugin = "maven")
apply(plugin = "com.github.johnrengelman.shadow")
apply(plugin = "com.jfrog.artifactory")
configurations {
create("shade")
getByName("archives").extendsFrom(getByName("default"))
}
group = "${rootProject.group}.worldguard-libs"
tasks.register<ShadowJar>("jar") {
configurations = listOf(project.configurations["shade"])
archiveClassifier.set("")
dependencies {
exclude(dependency("com.google.code.findbugs:jsr305:1.3.9"))
}
relocate("com.sk89q.squirrelid", "com.sk89q.worldguard.util.profile")
}
val altConfigFiles = { artifactType: String ->
val deps = configurations["shade"].incoming.dependencies
.filterIsInstance<ModuleDependency>()
.map { it.copy() }
.map { dependency ->
dependency.artifact {
name = dependency.name
type = artifactType
extension = "jar"
classifier = artifactType
}
dependency
}
files(configurations.detachedConfiguration(*deps.toTypedArray())
.resolvedConfiguration.lenientConfiguration.artifacts
.filter { it.classifier == artifactType }
.map { zipTree(it.file) })
}
tasks.register<Jar>("sourcesJar") {
from({
altConfigFiles("sources")
})
val filePattern = Regex("(.*)com/sk89q/squirrelid((?:/|$).*)")
val textPattern = Regex("com\\.sk89q\\.squirrelid")
eachFile {
filter {
it.replaceFirst(textPattern, "com.sk89q.worldguard.util.profile")
}
path = path.replaceFirst(filePattern, "$1com/sk89q/worldguard/util/profile$2")
}
archiveClassifier.set("sources")
}
tasks.named("assemble").configure {
dependsOn("jar", "sourcesJar")
}
artifacts {
val jar = tasks.named("jar")
add("default", jar) {
builtBy(jar)
}
val sourcesJar = tasks.named("sourcesJar")
add("archives", sourcesJar) {
builtBy(sourcesJar)
}
}
tasks.register<Upload>("install") {
configuration = configurations["archives"]
(repositories as HasConvention).convention.getPlugin<MavenRepositoryHandlerConvention>().mavenInstaller {
pom.version = project.version.toString()
pom.artifactId = project.name
}
}
applyCommonArtifactoryConfig()
}
-119
View File
@@ -1,119 +0,0 @@
import com.github.jengelman.gradle.plugins.shadow.tasks.ShadowJar
import net.minecrell.gradle.licenser.LicenseExtension
import org.gradle.api.JavaVersion
import org.gradle.api.Project
import org.gradle.api.plugins.JavaPluginConvention
import org.gradle.api.plugins.quality.CheckstyleExtension
import org.gradle.api.tasks.bundling.Jar
import org.gradle.api.tasks.javadoc.Javadoc
import org.gradle.api.tasks.testing.Test
import org.gradle.external.javadoc.CoreJavadocOptions
import org.gradle.kotlin.dsl.apply
import org.gradle.kotlin.dsl.configure
import org.gradle.kotlin.dsl.dependencies
import org.gradle.kotlin.dsl.get
import org.gradle.kotlin.dsl.getByName
import org.gradle.kotlin.dsl.named
import org.gradle.kotlin.dsl.register
import org.gradle.kotlin.dsl.withType
fun Project.applyPlatformAndCoreConfiguration() {
applyCommonConfiguration()
apply(plugin = "java")
apply(plugin = "eclipse")
apply(plugin = "idea")
apply(plugin = "maven")
apply(plugin = "checkstyle")
apply(plugin = "com.github.johnrengelman.shadow")
apply(plugin = "com.jfrog.artifactory")
apply(plugin = "net.minecrell.licenser")
ext["internalVersion"] = "$version;${rootProject.ext["gitCommitHash"]}"
configure<JavaPluginConvention> {
sourceCompatibility = JavaVersion.VERSION_1_8
targetCompatibility = JavaVersion.VERSION_1_8
}
configure<CheckstyleExtension> {
configFile = rootProject.file("config/checkstyle/checkstyle.xml")
toolVersion = "7.6.1"
}
tasks.withType<Test>().configureEach {
useJUnit()
}
dependencies {
"testCompile"("junit:junit:${Versions.JUNIT}")
// TODO switch to jupiter - doesn't support abstract test classes so tests need rewriting
//"testImplementation"("org.junit.jupiter:junit-jupiter-api:${Versions.JUNIT}")
//"testRuntime"("org.junit.jupiter:junit-jupiter-engine:${Versions.JUNIT}")
}
// Java 8 turns on doclint which we fail
tasks.withType<Javadoc>().configureEach {
(options as CoreJavadocOptions).addStringOption("Xdoclint:none", "-quiet")
}
tasks.register<Jar>("javadocJar") {
dependsOn("javadoc")
archiveClassifier.set("javadoc")
from(tasks.getByName<Javadoc>("javadoc").destinationDir)
}
tasks.named("assemble").configure {
dependsOn("javadocJar")
}
artifacts {
add("archives", tasks.named("jar"))
add("archives", tasks.named("javadocJar"))
}
if (name == "worldguard-core" || name == "worldguard-bukkit") {
tasks.register<Jar>("sourcesJar") {
dependsOn("classes")
archiveClassifier.set("sources")
from(sourceSets["main"].allSource)
}
artifacts {
add("archives", tasks.named("sourcesJar"))
}
tasks.named("assemble").configure {
dependsOn("sourcesJar")
}
}
tasks.named("check").configure {
dependsOn("checkstyleMain", "checkstyleTest")
}
applyCommonArtifactoryConfig()
configure<LicenseExtension> {
header = rootProject.file("HEADER.txt")
include("**/*.java")
}
}
fun Project.applyShadowConfiguration() {
tasks.named<ShadowJar>("shadowJar") {
archiveClassifier.set("dist")
dependencies {
include(project(":worldguard-libs:core"))
//include(project(":worldguard-libs:${project.name.replace("worldguard-", "")}"))
include(project(":worldguard-core"))
relocate("org.flywaydb", "com.sk89q.worldguard.internal.flywaydb") {
include(dependency("org.flywaydb:flyway-core:3.0"))
}
relocate("com.sk89q.squirrelid", "com.sk89q.worldguard.util.profile")
}
exclude("GradleStart**")
exclude(".cache")
exclude("LICENSE*")
}
}
-7
View File
@@ -1,7 +0,0 @@
object Versions {
// const val PISTON = "0.4.3"
// const val AUTO_VALUE = "1.6.5"
const val WORLDEDIT = "7.1.0-SNAPSHOT"
const val JUNIT = "4.11"
const val SQUIRRELID = "0.2.0"
}
-63
View File
@@ -1,63 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE module PUBLIC
"-//Puppy Crawl//DTD Check Configuration 1.3//EN"
"http://www.puppycrawl.com/dtds/configuration_1_3.dtd">
<module name="Checker">
<!-- Tabs are strictly banned -->
<module name="FileTabCharacter"/>
<module name="SuppressionFilter">
<property name="file" value="${config_loc}/suppressions.xml"/>
</module>
<module name="TreeWalker">
<!-- Important basics -->
<!-- <module name="PackageDeclaration"/> Unlikely that we would miss this in a PR -->
<module name="OuterTypeFilename"/> <!-- TypeName -> TypeName.java -->
<!--
Control package usage, so people don't insert Bukkit into WG where it shouldn't belong, etc.
It is a bit draconian, so update as necessary!
-->
<module name="ImportControl">
<property name="file" value="${config_loc}/import-control.xml"/>
</module>
<!-- Code -->
<module name="HideUtilityClassConstructor"/> <!-- Utility classes should not have a constructor -->
<module name="CovariantEquals"/>
<module name="EqualsHashCode"/> <!-- equals() and hashCode() go together -->
<module name="NestedTryDepth"> <!-- SHOULD not need to adjust this -->
<property name="max" value="2"/>
</module>
<module name="SuperFinalize"/> <!-- We don't actually use this -->
<!-- Style -->
<module name="LeftCurly"> <!-- Left brace never goes on another line -->
<property name="option" value="eol"/>
</module> <!-- We don't check right brace -->
<module name="DefaultComesLast"/> <!-- default case in switch should be last -->
<module name="GenericWhitespace"/>
<!-- Naming -->
<module name="ClassTypeParameterName">
<property name="format" value="^[A-Z][a-zA-Z0-9]*$"/>
</module>
<module name="LocalFinalVariableName"/>
<module name="LocalVariableName">
<property name="format" value="^[a-z_][a-zA-Z0-9]*$"/>
</module>
<module name="MemberName">
<property name="format" value="^[a-z_][a-zA-Z0-9]*$"/>
</module>
<module name="MethodName">
<property name="format" value="^[a-z][a-zA-Z0-9]*$"/>
</module>
<!-- <module name="PackageName"/> Unlikely that we would miss this in a PR -->
<module name="ParameterName"/>
<!-- <module name="TypeName"/> Unlikely that we would miss this in a PR -->
</module>
</module>
-36
View File
@@ -1,36 +0,0 @@
<!DOCTYPE import-control PUBLIC
"-//Puppy Crawl//DTD Import Control 1.1//EN"
"http://www.puppycrawl.com/dtds/import_control_1_1.dtd">
<import-control pkg="com.sk89q">
<allow pkg="java"/>
<allow pkg="javax"/>
<allow pkg="org.junit"/>
<allow pkg="org.hamcrest"/>
<allow pkg="org.mockito"/>
<allow pkg="junit.framework"/>
<allow pkg="com.sk89q"/>
<allow pkg="com.google.common"/>
<subpackage name="worldguard">
<allow pkg="org.khelekore"/>
<allow pkg="org.flywaydb"/>
<allow pkg="org.yaml"/>
<allow pkg="org.enginehub.piston"/>
<subpackage name="util.profile.resolver">
<allow pkg="org.bukkit"/>
<allow pkg="io.papermc.lib"/>
<allow pkg="com.destroystokyo.paper"/>
</subpackage>
<subpackage name="bukkit">
<allow pkg="org.bukkit"/>
<allow pkg="org.bstats.bukkit"/>
<allow pkg="io.papermc.lib"/>
<allow pkg="com.destroystokyo.paper"/>
</subpackage>
</subpackage>
</import-control>
-7
View File
@@ -1,7 +0,0 @@
<?xml version="1.0"?>
<!DOCTYPE suppressions PUBLIC
"-//Checkstyle//DTD SuppressionFilter Configuration 1.2//EN"
"https://checkstyle.org/dtds/suppressions_1_2.dtd">
<suppressions>
<suppress files="ProtectedRegion.java" checks="EqualsHashCode"/>
</suppressions>
File renamed without changes.
-2
View File
@@ -1,2 +0,0 @@
group=com.sk89q.worldguard
version=7.0.2-SNAPSHOT
Binary file not shown.
-5
View File
@@ -1,5 +0,0 @@
distributionBase=GRADLE_USER_HOME
distributionPath=wrapper/dists
distributionUrl=https\://services.gradle.org/distributions/gradle-5.5.1-all.zip
zipStoreBase=GRADLE_USER_HOME
zipStorePath=wrapper/dists
Vendored
-172
View File
@@ -1,172 +0,0 @@
#!/usr/bin/env sh
##############################################################################
##
## Gradle start up script for UN*X
##
##############################################################################
# Attempt to set APP_HOME
# Resolve links: $0 may be a link
PRG="$0"
# Need this for relative symlinks.
while [ -h "$PRG" ] ; do
ls=`ls -ld "$PRG"`
link=`expr "$ls" : '.*-> \(.*\)$'`
if expr "$link" : '/.*' > /dev/null; then
PRG="$link"
else
PRG=`dirname "$PRG"`"/$link"
fi
done
SAVED="`pwd`"
cd "`dirname \"$PRG\"`/" >/dev/null
APP_HOME="`pwd -P`"
cd "$SAVED" >/dev/null
APP_NAME="Gradle"
APP_BASE_NAME=`basename "$0"`
# Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
DEFAULT_JVM_OPTS='"-Xmx64m"'
# Use the maximum available, or set MAX_FD != -1 to use that value.
MAX_FD="maximum"
warn () {
echo "$*"
}
die () {
echo
echo "$*"
echo
exit 1
}
# OS specific support (must be 'true' or 'false').
cygwin=false
msys=false
darwin=false
nonstop=false
case "`uname`" in
CYGWIN* )
cygwin=true
;;
Darwin* )
darwin=true
;;
MINGW* )
msys=true
;;
NONSTOP* )
nonstop=true
;;
esac
CLASSPATH=$APP_HOME/gradle/wrapper/gradle-wrapper.jar
# Determine the Java command to use to start the JVM.
if [ -n "$JAVA_HOME" ] ; then
if [ -x "$JAVA_HOME/jre/sh/java" ] ; then
# IBM's JDK on AIX uses strange locations for the executables
JAVACMD="$JAVA_HOME/jre/sh/java"
else
JAVACMD="$JAVA_HOME/bin/java"
fi
if [ ! -x "$JAVACMD" ] ; then
die "ERROR: JAVA_HOME is set to an invalid directory: $JAVA_HOME
Please set the JAVA_HOME variable in your environment to match the
location of your Java installation."
fi
else
JAVACMD="java"
which java >/dev/null 2>&1 || die "ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.
Please set the JAVA_HOME variable in your environment to match the
location of your Java installation."
fi
# Increase the maximum file descriptors if we can.
if [ "$cygwin" = "false" -a "$darwin" = "false" -a "$nonstop" = "false" ] ; then
MAX_FD_LIMIT=`ulimit -H -n`
if [ $? -eq 0 ] ; then
if [ "$MAX_FD" = "maximum" -o "$MAX_FD" = "max" ] ; then
MAX_FD="$MAX_FD_LIMIT"
fi
ulimit -n $MAX_FD
if [ $? -ne 0 ] ; then
warn "Could not set maximum file descriptor limit: $MAX_FD"
fi
else
warn "Could not query maximum file descriptor limit: $MAX_FD_LIMIT"
fi
fi
# For Darwin, add options to specify how the application appears in the dock
if $darwin; then
GRADLE_OPTS="$GRADLE_OPTS \"-Xdock:name=$APP_NAME\" \"-Xdock:icon=$APP_HOME/media/gradle.icns\""
fi
# For Cygwin, switch paths to Windows format before running java
if $cygwin ; then
APP_HOME=`cygpath --path --mixed "$APP_HOME"`
CLASSPATH=`cygpath --path --mixed "$CLASSPATH"`
JAVACMD=`cygpath --unix "$JAVACMD"`
# We build the pattern for arguments to be converted via cygpath
ROOTDIRSRAW=`find -L / -maxdepth 1 -mindepth 1 -type d 2>/dev/null`
SEP=""
for dir in $ROOTDIRSRAW ; do
ROOTDIRS="$ROOTDIRS$SEP$dir"
SEP="|"
done
OURCYGPATTERN="(^($ROOTDIRS))"
# Add a user-defined pattern to the cygpath arguments
if [ "$GRADLE_CYGPATTERN" != "" ] ; then
OURCYGPATTERN="$OURCYGPATTERN|($GRADLE_CYGPATTERN)"
fi
# Now convert the arguments - kludge to limit ourselves to /bin/sh
i=0
for arg in "$@" ; do
CHECK=`echo "$arg"|egrep -c "$OURCYGPATTERN" -`
CHECK2=`echo "$arg"|egrep -c "^-"` ### Determine if an option
if [ $CHECK -ne 0 ] && [ $CHECK2 -eq 0 ] ; then ### Added a condition
eval `echo args$i`=`cygpath --path --ignore --mixed "$arg"`
else
eval `echo args$i`="\"$arg\""
fi
i=$((i+1))
done
case $i in
(0) set -- ;;
(1) set -- "$args0" ;;
(2) set -- "$args0" "$args1" ;;
(3) set -- "$args0" "$args1" "$args2" ;;
(4) set -- "$args0" "$args1" "$args2" "$args3" ;;
(5) set -- "$args0" "$args1" "$args2" "$args3" "$args4" ;;
(6) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" ;;
(7) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" ;;
(8) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" ;;
(9) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" "$args8" ;;
esac
fi
# Escape application args
save () {
for i do printf %s\\n "$i" | sed "s/'/'\\\\''/g;1s/^/'/;\$s/\$/' \\\\/" ; done
echo " "
}
APP_ARGS=$(save "$@")
# Collect all arguments for the java command, following the shell quoting and substitution rules
eval set -- $DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS "\"-Dorg.gradle.appname=$APP_BASE_NAME\"" -classpath "\"$CLASSPATH\"" org.gradle.wrapper.GradleWrapperMain "$APP_ARGS"
# by default we should be in the correct project dir, but when run from Finder on Mac, the cwd is wrong
if [ "$(uname)" = "Darwin" ] && [ "$HOME" = "$PWD" ]; then
cd "$(dirname "$0")"
fi
exec "$JAVACMD" "$@"
Vendored
-84
View File
@@ -1,84 +0,0 @@
@if "%DEBUG%" == "" @echo off
@rem ##########################################################################
@rem
@rem Gradle startup script for Windows
@rem
@rem ##########################################################################
@rem Set local scope for the variables with windows NT shell
if "%OS%"=="Windows_NT" setlocal
set DIRNAME=%~dp0
if "%DIRNAME%" == "" set DIRNAME=.
set APP_BASE_NAME=%~n0
set APP_HOME=%DIRNAME%
@rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
set DEFAULT_JVM_OPTS="-Xmx64m"
@rem Find java.exe
if defined JAVA_HOME goto findJavaFromJavaHome
set JAVA_EXE=java.exe
%JAVA_EXE% -version >NUL 2>&1
if "%ERRORLEVEL%" == "0" goto init
echo.
echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.
echo.
echo Please set the JAVA_HOME variable in your environment to match the
echo location of your Java installation.
goto fail
:findJavaFromJavaHome
set JAVA_HOME=%JAVA_HOME:"=%
set JAVA_EXE=%JAVA_HOME%/bin/java.exe
if exist "%JAVA_EXE%" goto init
echo.
echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME%
echo.
echo Please set the JAVA_HOME variable in your environment to match the
echo location of your Java installation.
goto fail
:init
@rem Get command-line arguments, handling Windows variants
if not "%OS%" == "Windows_NT" goto win9xME_args
:win9xME_args
@rem Slurp the command line arguments.
set CMD_LINE_ARGS=
set _SKIP=2
:win9xME_args_slurp
if "x%~1" == "x" goto execute
set CMD_LINE_ARGS=%*
:execute
@rem Setup the command line
set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar
@rem Execute Gradle
"%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %CMD_LINE_ARGS%
:end
@rem End local scope for the variables with windows NT shell
if "%ERRORLEVEL%"=="0" goto mainEnd
:fail
rem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of
rem the _cmd.exe /c_ return code!
if not "" == "%GRADLE_EXIT_CONSOLE%" exit 1
exit /b 1
:mainEnd
if "%OS%"=="Windows_NT" endlocal
:omega
+274
View File
@@ -0,0 +1,274 @@
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>com.sk89q</groupId>
<artifactId>worldguard</artifactId>
<version>5.7-SNAPSHOT</version>
<name>WorldGuard</name>
<description>WorldGuard protects your Minecraft servers.</description>
<licenses>
<license>
<name>GNU General Public License 2.0</name>
<url>LICENSE.txt</url>
<distribution>repo</distribution>
<comments>License on all contributions</comments>
</license>
</licenses>
<scm>
<connection>scm:git:git://github.com/sk89q/worldguard.git</connection>
<url>https://github.com/sk89q/worldguard</url>
<tag>master</tag>
<developerConnection>scm:git:git@github.com:sk89q/worldguard.git</developerConnection>
</scm>
<properties>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
</properties>
<repositories>
<repository>
<id>sk89q-repo</id>
<url>http://maven.sk89q.com/repo/</url>
</repository>
<repository>
<id>zml-repo</id>
<url>http://files.zachsthings.com/repo</url>
</repository>
<repository>
<id>bukkit-repo</id>
<url>http://repo.bukkit.org/content/groups/public</url>
</repository>
</repositories>
<dependencies>
<dependency>
<groupId>com.sk89q</groupId>
<artifactId>worldedit</artifactId>
<version>5.4.4</version>
<scope>compile</scope>
</dependency>
<dependency>
<groupId>com.sk89q</groupId>
<artifactId>rebar</artifactId>
<version>4.1.0-SNAPSHOT</version>
<scope>compile</scope>
</dependency>
<dependency>
<groupId>org.bukkit</groupId>
<artifactId>bukkit</artifactId>
<version>1.4.2-R0.2-SNAPSHOT</version>
<scope>compile</scope>
</dependency>
<dependency>
<groupId>com.sk89q</groupId>
<artifactId>commandbook</artifactId>
<version>2.1</version>
<scope>compile</scope>
<exclusions>
<exclusion>
<groupId>com.zachsthings.libcomponents</groupId>
<artifactId>libcomponents-bukkit</artifactId>
</exclusion>
<exclusion>
<groupId>org.spout</groupId>
<artifactId>spoutapi</artifactId>
</exclusion>
</exclusions>
</dependency>
<dependency>
<groupId>com.nijikokun</groupId>
<artifactId>iconomy</artifactId>
<version>5.0</version>
<scope>compile</scope>
</dependency>
<dependency>
<groupId>org.khelekore</groupId>
<artifactId>prtree</artifactId>
<version>1.5.0</version>
<scope>compile</scope>
</dependency>
<dependency>
<groupId>net.sf.opencsv</groupId>
<artifactId>opencsv</artifactId>
<version>2.0</version>
<scope>compile</scope>
</dependency>
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>4.8.1</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>commons-lang</groupId>
<artifactId>commons-lang</artifactId>
<version>2.3</version>
<scope>compile</scope>
</dependency>
<dependency>
<groupId>com.jolbox</groupId>
<artifactId>bonecp</artifactId>
<version>0.7.1.RELEASE</version>
<scope>compile</scope>
</dependency>
<dependency>
<groupId>org.mockito</groupId>
<artifactId>mockito-all</artifactId>
<version>1.9.5</version>
<scope>test</scope>
</dependency>
</dependencies>
<distributionManagement>
<site>
<id>sk89q-docs-upload</id>
<url>ftp://sk89q-maven-deploy/worldguard/</url>
</site>
</distributionManagement>
<build>
<defaultGoal>install</defaultGoal>
<sourceDirectory>${basedir}/src/main/java</sourceDirectory>
<extensions>
<extension>
<groupId>org.apache.maven.wagon</groupId>
<artifactId>wagon-ftp</artifactId>
<version>1.0-beta-6</version>
</extension>
</extensions>
<resources>
<resource>
<targetPath>.</targetPath>
<filtering>true</filtering>
<directory>${basedir}/src/main/resources/</directory>
<includes>
<include>plugin.yml</include>
</includes>
</resource>
<resource>
<targetPath>defaults/</targetPath>
<filtering>true</filtering>
<directory>${basedir}/src/main/resources/</directory>
<includes>
<include>blacklist.txt</include>
<include>builtin_rules.yml</include>
<include>rulelist.yml</include>
</includes>
</resource>
<resource>
<targetPath></targetPath>
<filtering>false</filtering>
<directory>${basedir}/src/main/resources/</directory>
<includes>
<include>models/</include>
<include>sql/</include>
</includes>
</resource>
</resources>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<version>2.3.2</version>
<configuration>
<source>1.6</source>
<target>1.6</target>
</configuration>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-jar-plugin</artifactId>
<version>2.3.1</version>
<configuration>
<archive>
<addMavenDescriptor>true</addMavenDescriptor>
<manifest>
<addDefaultSpecificationEntries>true</addDefaultSpecificationEntries>
<addDefaultImplementationEntries>true</addDefaultImplementationEntries>
</manifest>
<manifestEntries>
<Class-Path>WorldGuard/WorldEdit.jar lib/WorldEdit.jar ../lib/WorldEdit.jar ../WorldEdit.jar</Class-Path>
</manifestEntries>
</archive>
</configuration>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-shade-plugin</artifactId>
<version>1.4</version>
<executions>
<execution>
<phase>package</phase>
<goals>
<goal>shade</goal>
</goals>
<configuration>
<artifactSet>
<includes>
<include>net.sf.opencsv:opencsv</include>
<include>org.khelekore:prtree</include>
<include>com.sk89q:rebar</include>
</includes>
</artifactSet>
</configuration>
</execution>
</executions>
</plugin>
<plugin>
<artifactId>maven-assembly-plugin</artifactId>
<version>2.2-beta-2</version>
<configuration>
<descriptor>${basedir}/src/main/assembly/default.xml</descriptor>
</configuration>
<executions>
<execution>
<id>release</id>
<phase>package</phase>
<goals>
<goal>single</goal>
</goals>
</execution>
</executions>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-release-plugin</artifactId>
<version>2.2.2</version>
<configuration>
<preparationGoals>assembly:assembly</preparationGoals>
<goals>assembly:assembly</goals>
<tagNameFormat>@{project.version}</tagNameFormat>
</configuration>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-site-plugin</artifactId>
<version>3.1</version>
<configuration>
<reportPlugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-project-info-reports-plugin</artifactId>
<version>2.5</version>
<reportSets>
<reportSet>
<reports>
<report>license</report>
<report>index</report>
</reports>
</reportSet>
</reportSets>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-javadoc-plugin</artifactId>
<version>2.8.1</version>
</plugin>
</reportPlugins>
</configuration>
</plugin>
</plugins>
</build>
</project>
-7
View File
@@ -1,7 +0,0 @@
rootProject.name = "worldguard"
include("worldguard-libs")
include("worldguard-libs:core")
include("worldguard-core")
//include("worldguard-libs:bukkit")
include("worldguard-bukkit")
+38
View File
@@ -0,0 +1,38 @@
<?xml version="1.0" encoding="UTF-8"?>
<assembly
xmlns="http://maven.apache.org/plugins/maven-assembly-plugin/assembly/1.1.2"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/plugins/maven-assembly-plugin/assembly/1.1.2 http://maven.apache.org/xsd/assembly-1.1.2.xsd">
<id>default</id>
<includeBaseDirectory>false</includeBaseDirectory>
<formats>
<format>tar.gz</format>
<format>tar.bz2</format>
<format>zip</format>
</formats>
<files>
<file>
<source>${project.build.directory}/${artifactId}-${project.version}.jar</source>
<destName>WorldGuard.jar</destName>
<outputDirectory>/</outputDirectory>
<filtered>false</filtered>
</file>
<file>
<source>README.html</source>
<outputDirectory>/</outputDirectory>
<filtered>true</filtered>
</file>
</files>
<fileSets>
<fileSet>
<includes>
<include>LICENSE.txt</include>
<include>NOTICE.txt</include>
<include>CHANGELOG.txt</include>
<include>contrib/blacklist_table.sql</include>
<include>contrib/region_storage.sql</include>
<include>contrib/region_storage_update_20110325.sql</include>
</includes>
</fileSet>
</fileSets>
</assembly>
@@ -0,0 +1,35 @@
// $Id$
/*
* This file is a part of WorldGuard.
* Copyright (c) sk89q <http://www.sk89q.com>
* Copyright (c) the 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
* (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
* GNU 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.rulelists;
/**
* An action that will be performed if the conditions are matched of the rule.
*
* @param <T> implementation-specific context object
*/
public interface Action<T extends Context> {
/**
* Apply the action.
*
* @param context implementation-specific context object
*/
void apply(T context);
}
@@ -0,0 +1,75 @@
// $Id$
/*
* This file is a part of WorldGuard.
* Copyright (c) sk89q <http://www.sk89q.com>
* Copyright (c) the 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
* (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
* GNU 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.rulelists;
/**
* An attachment is analogous to an event.
*/
public final class Attachment {
private static int NEXT_ID = 0;
private final int id;
private final String alias;
/**
* Create a new attachment with the given alias. The alias is used in rule list
* files.
*
* @param alias alias name
*/
public Attachment(String alias) {
this.alias = alias;
// No internal ID
id = -1;
}
/**
* Create a new attachment with the given alias. The alias is used in rule list
* files.
*
* @param alias alias name
* @param isInternal true to assign this attachment a standard internal ID
*/
Attachment(String alias, boolean isInternal) {
this.alias = alias;
id = isInternal ? NEXT_ID++ : -1;
}
/**
* Get the internal ID.
*
* @return ID number, possibly -1 for no internal ID
*/
int getId() {
return id;
}
/**
* Get the alias used inside rule list files.
*
* @return alias
*/
public String getAlias() {
return alias;
}
}
@@ -0,0 +1,77 @@
// $Id$
/*
* This file is a part of WorldGuard.
* Copyright (c) sk89q <http://www.sk89q.com>
* Copyright (c) the 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
* (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
* GNU 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.rulelists;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Map;
import java.util.Set;
import com.sk89q.rebar.config.Loader;
import com.sk89q.rebar.config.LoaderBuilderException;
/**
* A database of valid attachments.
*/
public final class AttachmentManager implements Loader<Attachment> {
private Set<Attachment> attachments = new HashSet<Attachment>();
private Map<String, Attachment> aliasMap = new HashMap<String, Attachment>();
public AttachmentManager() {
}
/**
* Register an attachment.
*
* @param attachment the attachment
*/
public synchronized void register(Attachment attachment) {
if (attachments.contains(attachment)
|| aliasMap.containsKey(attachment.getAlias().toLowerCase())) {
throw new IllegalArgumentException("Attachment '" + attachment + "' already registered.");
}
attachments.add(attachment);
aliasMap.put(attachment.getAlias().toLowerCase(), attachment);
}
/**
* Get an attachment by its alias.
*
* @param alias alias, case in-sensitive
* @return an attachment or null
*/
public synchronized Attachment lookup(String alias) {
return aliasMap.get(alias.toLowerCase());
}
@Override
public Attachment read(Object value) throws LoaderBuilderException {
String id = String.valueOf(value);
Attachment attachment = lookup(id);
if (attachment == null) {
throw new LoaderBuilderException("Unknown RuleList attachment: " + id);
}
return attachment;
}
}
@@ -0,0 +1,88 @@
// $Id$
/*
* This file is a part of WorldGuard.
* Copyright (c) sk89q <http://www.sk89q.com>
* Copyright (c) the 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
* (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
* GNU 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.rulelists;
/**
* A context has some shared variables that may be used by a number of different
* events. Because the context contains common information, criteria and
* actions do not have to be custom tailored to specific implementation-specific
* events, and can refer to the the properties set on the context. The place
* where the information is known as to what is considered the proper valid
* value of a common property is during the initial handling of
* the event in the implementation.
* </p>
* Implementations need to have custom contexts that can carry more
* information than offered in this abstract implementation. Criteria and
* actions can be implement-specific by tailoring themselves to one of these
* implementation-specific contexts.
*
* @author sk89q
*/
public abstract class Context {
private boolean matches = false;
private boolean cancelled = false;
/**
* Gets whether the event associated with this context has been set to
* be cancelled.
*
* @return true if the event is set to be cancelled
*/
public boolean isCancelled() {
return cancelled;
}
/**
* Set the event associated with this context to be cancelled, if possible.
*/
public void cancel() {
setCancelled(true);
}
/**
* Set the event associated with this context to be cancelled, if possible.
*
* @param cancelled true to cancel
*/
public void setCancelled(boolean cancelled) {
this.cancelled = cancelled;
}
/**
* Set as to whether all the conditions associated with this context have
* evaluated to being true.
*
* @param matches match state
*/
void setMatches(boolean matches) {
this.matches = matches;
}
/**
* Returns whether all the conditions associated with this context
* have been evaluated to true.
*
* @return true if all the conditions have been true
*/
public boolean matches() {
return matches;
}
}
@@ -0,0 +1,37 @@
// $Id$
/*
* This file is a part of WorldGuard.
* Copyright (c) sk89q <http://www.sk89q.com>
* Copyright (c) the 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
* (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
* GNU 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.rulelists;
/**
* A criteria that is evaluated to decide whether the rule should undergo
* further processing.
*
* @param <T> an implementation-specific context
*/
public interface Criteria<T extends Context> {
/**
* Returns whether the current event / context matches this criteria.
*
* @param context context to verify
* @return true if it matches
*/
boolean matches(T context);
}
@@ -0,0 +1,80 @@
// $Id$
/*
* This file is a part of WorldGuard.
* Copyright (c) sk89q <http://www.sk89q.com>
* Copyright (c) the 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
* (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
* GNU 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.rulelists;
import java.lang.reflect.Field;
import java.lang.reflect.Modifier;
/**
* Contains names of standard attachments.
*/
public final class DefaultAttachments {
public final static Attachment BLOCK_BREAK = new Attachment("block-break", true);
public final static Attachment BLOCK_PLACE = new Attachment("block-place", true);
public final static Attachment BLOCK_SPREAD = new Attachment("block-spread", true);
public final static Attachment BLOCK_PHYSICS = new Attachment("block-physics", true);
public final static Attachment BLOCK_INTERACT = new Attachment("block-interact", true);
public final static Attachment BLOCK_FADE = new Attachment("block-fade", true);
public final static Attachment BLOCK_FORM = new Attachment("block-form", true);
public final static Attachment PLAYER_JOIN = new Attachment("player-join", true);
public final static Attachment PLAYER_RESPAWN = new Attachment("player-respawn", true);
public final static Attachment PLAYER_QUIT = new Attachment("player-quit", true);
public final static Attachment ENTITY_EXPLODE = new Attachment("entity-explode", true);
public final static Attachment ENTITY_DAMAGE = new Attachment("entity-damage", true);
public final static Attachment ENTITY_DEATH = new Attachment("entity-death", true);
public final static Attachment ENTITY_IGNITE = new Attachment("entity-ignite", true);
public final static Attachment ENTITY_SPAWN = new Attachment("entity-spawn", true);
public final static Attachment ENTITY_STRIKE = new Attachment("entity-strike", true);
public final static Attachment ENTITY_INTERACT = new Attachment("entity-interact", true);
public final static Attachment CHAT = new Attachment("chat", true);
public final static Attachment ITEM_DROP = new Attachment("item-drop", true);
public final static Attachment ITEM_PICKUP = new Attachment("item-pickup", true);
public final static Attachment ITEM_USE = new Attachment("item-use", true);
public final static Attachment WEATHER_PHENOMENON = new Attachment("weather-phenomenon", true);
public final static Attachment WEATHER_TRANSITION = new Attachment("weather-transition", true);
public final static Attachment WORLD_LOAD = new Attachment("world-load", true);
public final static Attachment WORLD_UNLOAD = new Attachment("world-unload", true);
public final static Attachment WORLD_SAVE = new Attachment("world-save", true);
private DefaultAttachments() {
}
/**
* Register the attachments in this class with the given manager.
*
* @param manager the manager
*/
public static void registerWith(AttachmentManager manager) {
for (Field field : DefaultAttachments.class.getFields()) {
if (Modifier.isStatic(field.getModifiers())
&& Attachment.class.isAssignableFrom(field.getType())) {
try {
manager.register((Attachment) field.get(null));
} catch (IllegalArgumentException e) {
throw new RuntimeException("Failed to register default attachment", e);
} catch (IllegalAccessException e) {
throw new RuntimeException("Failed to register default attachment", e);
}
}
}
}
}
@@ -0,0 +1,99 @@
// $Id$
/*
* This file is a part of WorldGuard.
* Copyright (c) sk89q <http://www.sk89q.com>
* Copyright (c) the 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
* (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
* GNU 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.rulelists;
import java.util.LinkedList;
import java.util.List;
import java.util.logging.Level;
import java.util.logging.Logger;
/**
* A {@link Rule} implementation with a list of {@link Criteria} and
* {@link Action}s.
*
* @param <T> underlying implementation-specific context
*/
public class DefinedRule<T extends Context> implements Rule<T> {
private static Logger logger = Logger.getLogger(Rule.class.getCanonicalName());
private final List<Criteria<T>> criterion = new LinkedList<Criteria<T>>();
private final List<Action<T>> actions = new LinkedList<Action<T>>();
/**
* Add a criteria to this rule.
*
* @param criteria the criteria
*/
public void add(Criteria<T> criteria) {
criterion.add(criteria);
}
/**
* Add an action to this rule.
*
* @param action the action
*/
public void add(Action<T> action) {
actions.add(action);
}
/**
* Returns whether criteria are defined.
*
* @return true if there are criteria
*/
public boolean hasCriterion() {
return criterion.size() > 0;
}
/**
* Returns whether actions are defined.
*
* @return true if there are actions
*/
public boolean hasActions() {
return actions.size() > 0;
}
@Override
public boolean matches(T context) {
for (Criteria<T> criteria : criterion) {
if (!criteria.matches(context)) {
context.setMatches(false);
return false;
}
}
context.setMatches(true);
return true;
}
@Override
public void apply(T context) {
for (Action<T> action : actions) {
try {
action.apply(context);
} catch (Throwable t) {
logger.log(Level.WARNING, "Failed to apply action of rule", t);
}
}
}
}
@@ -0,0 +1,42 @@
// $Id$
/*
* This file is a part of WorldGuard.
* Copyright (c) sk89q <http://www.sk89q.com>
* Copyright (c) the 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
* (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
* GNU 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.rulelists;
import com.sk89q.rebar.config.LoaderBuilderException;
public class DefinitionException extends LoaderBuilderException {
private static final long serialVersionUID = -5429457695711163632L;
public DefinitionException() {
}
public DefinitionException(String message) {
super(message);
}
public DefinitionException(Throwable cause) {
super(cause);
}
public DefinitionException(String message, Throwable cause) {
super(message, cause);
}
}
@@ -0,0 +1,47 @@
// $Id$
/*
* This file is a part of WorldGuard.
* Copyright (c) sk89q <http://www.sk89q.com>
* Copyright (c) the 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
* (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
* GNU 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.rulelists;
import org.bukkit.event.Event;
import org.bukkit.event.HandlerList;
public class DefinitionInitializeEvent extends Event {
private static final HandlerList handlers = new HandlerList();
private final RuleListsManager ruleListsManager;
public DefinitionInitializeEvent(RuleListsManager ruleListsManager) {
this.ruleListsManager = ruleListsManager;
}
public RuleListsManager getManager() {
return ruleListsManager;
}
@Override
public HandlerList getHandlers() {
return handlers;
}
public static HandlerList getHandlerList() {
return handlers;
}
}
@@ -0,0 +1,76 @@
// $Id$
/*
* This file is a part of WorldGuard.
* Copyright (c) sk89q <http://www.sk89q.com>
* Copyright (c) the 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
* (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
* GNU 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.rulelists;
import java.util.HashMap;
import java.util.Map;
import com.sk89q.rebar.config.ConfigurationNode;
import com.sk89q.rebar.config.ConfigurationValue;
import com.sk89q.rebar.config.Loader;
/**
* Manages loaders for definitions of the given generic type.
*
* @author sk89q
* @param <V> type to create
*/
public class DefinitionManager<V> {
/**
* Map of factories.
*/
private Map<String, Loader<? extends V>> factories = new HashMap<String, Loader<? extends V>>();
/**
* Register a loader.
*
* @param id ID, case does not matter
* @param factory factory
*/
public void register(String id, Loader<? extends V> factory) {
factories.put(id.toLowerCase(), factory);
}
/**
* Create a new instance.
*
* @param id type
* @param node configuration node
* @param value short-hand value, possibly null
* @return an object
* @throws DefinitionException thrown on error when parsing or instantiating
*/
V newInstance(String id, ConfigurationNode node, ConfigurationValue value) throws DefinitionException {
Loader<? extends V> factory;
if (value != null) {
node = node.clone();
node.set("_", value.get());
}
if ((factory = factories.get(id)) != null) {
return factory.read(node);
}
throw new DefinitionException("Don't know what '" + id
+ "' is (typo? criteria/action doesn't exist?)");
}
}
@@ -0,0 +1,35 @@
// $Id$
/*
* This file is a part of WorldGuard.
* Copyright (c) sk89q <http://www.sk89q.com>
* Copyright (c) the 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
* (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
* GNU 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.rulelists;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
public class ExpressionParser {
private static final char COLOR_CHAR = '\u00A7';
private static final Pattern classicColors = Pattern.compile("&[A-Fa-z0-9klmnor]");
public String format(Context context, String string) {
Matcher m = classicColors.matcher(string);
string = m.replaceAll(COLOR_CHAR + "$1");
return string;
}
}
@@ -0,0 +1,40 @@
// $Id$
/*
* This file is a part of WorldGuard.
* Copyright (c) sk89q <http://www.sk89q.com>
* Copyright (c) the 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
* (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
* GNU 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.rulelists;
/**
* A criteria wrapper that inverts the condition.
*
* @author sk89q
* @param <T> underlying criteria
*/
public class InvertedCriteria<T extends Context> implements Criteria<T> {
private final Criteria<T> criteria;
public InvertedCriteria(Criteria<T> criteria) {
this.criteria = criteria;
}
@Override
public boolean matches(T context) {
return !criteria.matches(context);
}
}
@@ -0,0 +1,30 @@
// $Id$
/*
* This file is a part of WorldGuard.
* Copyright (c) sk89q <http://www.sk89q.com>
* Copyright (c) the 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
* (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
* GNU 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.rulelists;
/**
* Attempts to resolve the requested object from other objects. For
* example, a block place event can have multiple 'relevant' blocks, such as
* the target block or the source block. A resolver is used to figure out
* which block is requested, and then the resolver would return the object
* requested by accessing it through a given context.
*/
public interface Resolver {
}
@@ -0,0 +1,63 @@
// $Id$
/*
* This file is a part of WorldGuard.
* Copyright (c) sk89q <http://www.sk89q.com>
* Copyright (c) the 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
* (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
* GNU 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.rulelists;
import java.util.HashMap;
import java.util.Map;
public class ResolverManager {
private final Map<Class<? extends Resolver>, Map<String, Resolver>> resolvers
= new HashMap<Class<? extends Resolver>, Map<String, Resolver>>();
private final Map<Resolver, String> reverse = new HashMap<Resolver, String>();
public <T extends Resolver> void register(Class<T> clazz, String id, T resolver) {
Map<String, Resolver> map = resolvers.get(clazz);
if (map == null) {
map = new HashMap<String, Resolver>();
resolvers.put(clazz, map);
}
reverse.put(resolver, id);
map.put(id.toLowerCase(), resolver);
}
public String getId(Object object) {
return reverse.get(object);
}
@SuppressWarnings("unchecked")
public <T extends Resolver> T get(Class<T> clazz, String id) throws DefinitionException {
Map<String, Resolver> map = resolvers.get(clazz);
if (map == null) {
throw new DefinitionException("Don't know how to resolve "
+ clazz.getCanonicalName());
}
Resolver resolver = map.get(id);
if (resolver == null) {
throw new DefinitionException("Don't know how to resolve "
+ clazz.getCanonicalName());
}
return (T) resolver;
}
}
@@ -0,0 +1,35 @@
// $Id$
/*
* This file is a part of WorldGuard.
* Copyright (c) sk89q <http://www.sk89q.com>
* Copyright (c) the 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
* (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
* GNU 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.rulelists;
/**
* A rule that may match a number of events and can be applied in
* a situation. See {@link DefinedRule} for a rule implementation that
* consists of constituent {@link Criteria}s and {@link Action}s.
*
* @author sk89q
* @param <T> implementation-specific context
*/
public interface Rule<T extends Context> {
boolean matches(T context);
void apply(T context);
}
@@ -0,0 +1,60 @@
// $Id$
/*
* This file is a part of WorldGuard.
* Copyright (c) sk89q <http://www.sk89q.com>
* Copyright (c) the 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
* (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
* GNU 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.rulelists;
import java.util.List;
/**
* A pair of attachments and a rule.
*/
public class RuleEntry {
private final List<Attachment> attachments;
private final Rule<?> rule;
/**
* Construct the rule entry with the list of attachments and rules.
*
* @param attachments attachment names
* @param rule rules
*/
public RuleEntry(List<Attachment> attachments, Rule<?> rule) {
this.attachments = attachments;
this.rule = rule;
}
/**
* Get the list of attachments.
*
* @return attachment
*/
public List<Attachment> getAttachments() {
return attachments;
}
/**
* Get the rule.
*
* @return rule
*/
public Rule<?> getRule() {
return rule;
}
}
@@ -0,0 +1,175 @@
// $Id$
/*
* This file is a part of WorldGuard.
* Copyright (c) sk89q <http://www.sk89q.com>
* Copyright (c) the 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
* (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
* GNU 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.rulelists;
import java.util.List;
import java.util.logging.Logger;
import com.sk89q.rebar.config.AbstractNodeLoader;
import com.sk89q.rebar.config.ConfigurationNode;
import com.sk89q.rebar.config.ConfigurationValue;
import com.sk89q.rebar.config.LoaderBuilderException;
import com.sk89q.rebar.util.LoggerUtils;
/**
* A loader that will load rule definitions for the RuleLists.
*/
public class RuleEntryLoader extends AbstractNodeLoader<RuleEntry> {
public static final String INLINE = "_";
private static final Logger logger = LoggerUtils.getLogger(RuleEntryLoader.class);
private final AttachmentManager attachmentManager;
private final DefinitionLoader<Criteria<?>> criteriaLoader;
private final DefinitionLoader<Action<?>> actionLoader;
/**
* Construct the loader.
*
* @param ruleListsManager the action lists manager
*/
public RuleEntryLoader(RuleListsManager ruleListsManager) {
attachmentManager = ruleListsManager.getAttachments();
criteriaLoader = new DefinitionLoader<Criteria<?>>(ruleListsManager.getCriterion(), true);
actionLoader = new DefinitionLoader<Action<?>>(ruleListsManager.getActions(), false);
}
@Override
@SuppressWarnings({ "rawtypes", "unchecked" })
public RuleEntry read(ConfigurationNode node) {
if (node.size() == 0) {
return null;
}
List<Attachment> when = node.listOf("when", attachmentManager);
// Check to see if the rule has any events defined
if (when.size() == 0) {
logger.warning("A rule has missing 'when' clause:\n" + node.toString());
return null;
}
try {
DefinedRule rule = new DefinedRule();
// Get criterion from the 'if' subnode
for (Criteria criteria : node.listOf("if", criteriaLoader)) {
rule.add(criteria);
}
// Get actions from the 'then' subnode
for (Action action : node.listOf("then", actionLoader)) {
rule.add(action);
}
// A rule needs actions!
if (rule.hasActions()) {
return new RuleEntry(when, rule);
} else {
logger.warning("The following rule has no actions in:\n" + node.toString());
return null;
}
} catch (LoaderBuilderException e) {
logger.warning("A rule had the error '" + e.getMessage() + ", and the rule is:\n" + node.toString());
return null;
}
}
/**
* Inverts an criteria, wrapping it in a {@link InvertedCriteria}.
*
* @param criteria to invert
* @param inverted true to invert (false to not)
* @return
*/
@SuppressWarnings({ "unchecked", "rawtypes" })
private static <V> V invertCriteria(V object, boolean inverted) {
if (object instanceof Criteria && inverted) {
return (V) new InvertedCriteria((Criteria<?>) object);
}
return object;
}
/**
* Loads specific definitions (criterion or actions) defined.
*
* @param <T> type of definition ({@link Action} or {@link Criteria})
*/
private class DefinitionLoader<T> extends AbstractNodeLoader<T> {
private final DefinitionManager<T> manager;
private final boolean strict;
/**
* Construct the object.
*
* @param manager the definition manager
* @param strict true to throw exceptions on error
*/
public DefinitionLoader(DefinitionManager<T> manager, boolean strict) {
this.manager = manager;
this.strict = strict;
}
@Override
public T read(ConfigurationNode node) {
String id = node.getString("?");
boolean inverted = node.getBoolean("negate", false);
try {
// Check for long hand notation (?: class)
if (id != null) {
return invertCriteria(manager.newInstance(id, node, null), inverted);
}
// Check for short-hand notation (?class: value)
for (String key : node.getKeys(ConfigurationNode.ROOT)) {
if (key.startsWith("?")) {
id = key;
Object value = node.get(key);
return invertCriteria(
manager.newInstance(key.substring(1), node, new ConfigurationValue(value)), inverted);
}
}
// No class defined!
logger.warning("RuleList: Missing '?' parameter in definition " +
"(to define what kind of criteria/action it is)");
return null;
} catch (DefinitionException e) {
logger.warning("RuleList: Invalid definition " +
"identified by type '" + id + "': " + e.getMessage());
// Throw an exception in strict mode
if (strict) {
throw new LoaderBuilderException("RuleList: Invalid definition " +
"identified by type '" + id + "': " + e.getMessage());
}
return null;
}
}
}
}
@@ -0,0 +1,83 @@
// $Id$
/*
* This file is a part of WorldGuard.
* Copyright (c) sk89q <http://www.sk89q.com>
* Copyright (c) the 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
* (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
* GNU 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.rulelists;
import java.util.HashMap;
import java.util.Map;
/**
* Holds all the rules.
*/
public class RuleList {
private Map<Attachment, RuleSet> collections = new HashMap<Attachment, RuleSet>();
/**
* Build a new instance.
*/
public RuleList() {
}
/**
* Get a rule set for a given attachment. A rule set is guaranteed to be
* returned for all given attachments.
*
* @param attachment the attachment
* @return the rule set
*/
public synchronized RuleSet get(Attachment attachment) {
RuleSet collection = collections.get(attachment);
if (collection == null) {
collection = new RuleSet();
collections.put(attachment, collection);
}
return collection;
}
/**
* Register a rule with this rule list.
*
* @param entry entry
*/
public void learn(RuleEntry entry) {
Rule<?> rule = entry.getRule();
for (Attachment attachment : entry.getAttachments()) {
learn(attachment, rule);
}
}
/**
* Register a rule with this rule list.
*
* @param attachment the attachment for the rule
* @param rule the rule itself
*/
public void learn(Attachment attachment, Rule<?> rule) {
get(attachment).learn(rule);
}
/**
* Forget all rules.
*/
public void clear() {
collections.clear();
}
}
@@ -0,0 +1,65 @@
// $Id$
/*
* This file is a part of WorldGuard.
* Copyright (c) sk89q <http://www.sk89q.com>
* Copyright (c) the 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
* (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
* GNU 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.rulelists;
import java.util.List;
import java.util.logging.Logger;
import com.sk89q.rebar.config.ConfigurationNode;
/**
* RuleList-related utility methods.
*/
public class RuleListUtils {
private RuleListUtils() {
}
/**
* Warn of unknown directives in a rule list block.
*
* @param node node
* @param logger the logger to send to
* @param expected expected keys
*/
public static void warnUnknown(ConfigurationNode node, Logger logger, String ... expected) {
List<String> keys = node.getKeys(ConfigurationNode.ROOT);
for (String key : keys) {
boolean found = false;
if (key.equals("?")) continue;
if (key.equals("negate")) continue;
if (key.equals("_")) continue;
if (key.length() > 0 && key.charAt(0) == '?') continue;
for (String expect : expected) {
if (expect.equals(key)) {
found = true;
break;
}
}
if (!found) {
logger.warning("[WorldGuard] RuleList: Unexpected parameter of '" + key + "' in " + node);
}
}
}
}
@@ -0,0 +1,77 @@
// $Id$
/*
* This file is a part of WorldGuard.
* Copyright (c) sk89q <http://www.sk89q.com>
* Copyright (c) the 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
* (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
* GNU 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.rulelists;
/**
* Manages action lists and details relevant to them.
*/
public class RuleListsManager {
private final AttachmentManager attachments = new AttachmentManager();
private final DefinitionManager<Criteria<?>> criterion = new DefinitionManager<Criteria<?>>();
private final DefinitionManager<Action<?>> actions = new DefinitionManager<Action<?>>();
private final ResolverManager subjectResolvers = new ResolverManager();
private final ExpressionParser exprParser = new ExpressionParser();
/**
* Get the attachment manager.
*
* @return the attachment manager
*/
public AttachmentManager getAttachments() {
return attachments;
}
/**
* Get the criterion manager.
*
* @return criterion manager
*/
public DefinitionManager<Criteria<?>> getCriterion() {
return criterion;
}
/**
* Get the actions manager.
*
* @return actions manager
*/
public DefinitionManager<Action<?>> getActions() {
return actions;
}
/**
* Get the subject resolvers manager.
*
* @return the subject resolvers manager
*/
public ResolverManager getResolvers() {
return subjectResolvers;
}
/**
* Get the expression parser.
*
* @return the expression parser
*/
public ExpressionParser getParser() {
return exprParser;
}
}
@@ -0,0 +1,93 @@
// $Id$
/*
* This file is a part of WorldGuard.
* Copyright (c) sk89q <http://www.sk89q.com>
* Copyright (c) the 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
* (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
* GNU 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.rulelists;
import java.util.Collections;
import java.util.LinkedList;
import java.util.List;
/**
* Holds a collection of rules that can be applied to a context.
*
* @see RuleList
*/
public class RuleSet {
private List<Rule<?>> rules = new LinkedList<Rule<?>>();
RuleSet() {
}
/**
* Add the given rule to this set.
*
* @param rule the rule
*/
public synchronized void learn(Rule<?> rule) {
rules.add(rule);
}
/**
* Forget all rules.
*/
public synchronized void clear() {
rules.clear();
}
/**
* Return whether this set has rules.
*
* @return true if there are rules
*/
public synchronized boolean hasRules() {
return rules.size() > 0;
}
/**
* Get the list of rules. The returned list cannot be modified.
*
* @return rule list
*/
public synchronized List<Rule<?>> getRules() {
return Collections.unmodifiableList(rules);
}
/**
* Apply this rule set onto the given context. Only one thread should call
* this method at a given time.
*
* @param context the context
* @return true if the event has been cancelled
*/
@SuppressWarnings({ "unchecked", "rawtypes" })
public boolean process(Context context) {
if (context.isCancelled()) {
return true; // Ignore cancelled events for now
}
for (Rule rule : rules) {
if (rule.matches(context)) {
rule.apply(context);
}
}
return context.isCancelled();
}
}
@@ -0,0 +1,131 @@
// $Id$
/*
* This file is a part of WorldGuard.
* Copyright (c) sk89q <http://www.sk89q.com>
* Copyright (c) the 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
* (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
* GNU 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.rulelists;
import java.util.ArrayList;
import java.util.List;
import com.sk89q.rebar.config.AbstractNodeLoader;
import com.sk89q.rebar.config.ConfigurationNode;
import com.sk89q.rebar.config.LoaderBuilderException;
import com.sk89q.rebar.config.types.StringLoaderBuilder;
/**
* A loader that will load the built-in rules used. It handles a slightly different
* format that also stores parameter information and other goodies.
*/
public class RuleTemplateEntryLoader extends AbstractNodeLoader<List<RuleEntry>> {
private static final StringLoaderBuilder stringLoader = new StringLoaderBuilder();
private final ConfigurationNode config;
private final RuleEntryLoader entryLoader;
/**
* Construct the loader with the given rule lists manager.
*
* @param manager the manager
* @param config the configuration node to read settings from
*/
public RuleTemplateEntryLoader(RuleListsManager manager, ConfigurationNode config) {
entryLoader = new RuleEntryLoader(manager);
this.config = config;
}
@Override
public List<RuleEntry> read(ConfigurationNode node) throws LoaderBuilderException {
List<RuleEntry> rules = new ArrayList<RuleEntry>();
List<String> settings = node.listOf("setting", stringLoader);
if (settings.size() == 0) {
throw new LoaderBuilderException("No 'setting' value in:\n" + node.toString());
}
String selectedSetting = settings.get(0);
String type = node.getString("type", "boolean");
if (settings.size() > 1) {
boolean migrate = false;
boolean found = false;
Object value = null;
for (String setting : settings) {
if (config.contains(setting)) {
value = config.get(setting);
found = true;
break;
} else {
migrate = true;
}
}
if (found && migrate) {
config.set(settings.get(0), value);
int i = 0;
for (String setting : settings) {
if (i++ != 0) {
config.remove(setting);
}
}
}
}
boolean active = false;
// See if the setting is active
if (type.equals("boolean")) {
boolean negate = node.getBoolean("negate", false);
boolean enabled = config.getBoolean(selectedSetting, negate);
if (negate) {
enabled = !enabled;
}
if (enabled) {
active = true;
}
} else if (type.equals("list")) {
Object val = config.get(selectedSetting);
if (val == null) {
config.set(selectedSetting, new ArrayList<Object>());
} else if (val instanceof List<?> && ((List<?>) val).size() > 0) {
active = true;
}
}
// Load the setting
if (active) {
List<String> paramPaths = node.getStringList("parameters.target", new ArrayList<String>());
if (paramPaths.size() > 0) {
Object val = config.get(selectedSetting);
for (String path : paramPaths) {
node.set(path, val);
}
}
for (RuleEntry rule : node.listOf("rules", entryLoader)) {
rules.add(rule);
}
}
return rules;
}
}
@@ -0,0 +1,26 @@
// $Id$
/*
* This file is a part of WorldGuard.
* Copyright (c) sk89q <http://www.sk89q.com>
* Copyright (c) the 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
* (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;
/**
* A user, group, or other object that describes a set of users.
*/
public interface Classifier {
}
@@ -0,0 +1,94 @@
// $Id$
/*
* WorldGuard
* Copyright (C) 2010 sk89q <http://www.sk89q.com>
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU 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 General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package com.sk89q.worldguard;
import com.sk89q.worldedit.Vector;
public abstract class LocalPlayer {
/**
* Get a player's name.
*
* @return The player's name
*/
public abstract String getName();
/**
* Returns true if the player is inside a group.
*
* @param group The group to check
* @return Whether this player is in {@code group}
*/
public abstract boolean hasGroup(String group);
/**
* Get the player's position.
*
* @return The player's position
*/
public abstract Vector getPosition();
/**
* Kick the player.
*
* @param msg The message to kick the player with
*/
public abstract void kick(String msg);
/**
* Ban the player.
*
* @param msg The message to ban the player with
*/
public abstract void ban(String msg);
/**
* Send the player a message;
*
* @param msg The message to send to the player
*/
public abstract void printRaw(String msg);
/**
* Get the player's list of groups.
*
* @return The groups this player is in
*/
public abstract String[] getGroups();
/**
* Returns whether a player has permission.
*
* @param perm The permission to check
* @return Whether this player has {@code perm}
*/
public abstract boolean hasPermission(String perm);
@Override
public boolean equals(Object obj) {
return obj instanceof LocalPlayer && ((LocalPlayer) obj).getName().equals(getName());
}
@Override
public int hashCode() {
return getName().hashCode();
}
}
@@ -0,0 +1,334 @@
// $Id$
/*
* WorldGuard
* Copyright (C) 2010 sk89q <http://www.sk89q.com>
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU 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 General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package com.sk89q.worldguard.blacklist;
import java.io.BufferedReader;
import java.io.File;
import java.io.FileReader;
import java.io.IOException;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.logging.Level;
import java.util.logging.Logger;
import org.bukkit.ChatColor;
import com.sk89q.worldedit.blocks.ItemType;
import com.sk89q.worldguard.LocalPlayer;
import com.sk89q.worldguard.blacklist.events.BlacklistEvent;
/**
*
* @author sk89q
*/
public abstract class Blacklist {
/**
* List of entries by block ID.
*/
private Map<Integer,List<BlacklistEntry>> blacklist
= new HashMap<Integer,List<BlacklistEntry>>();
/**
* Logger.
*/
private BlacklistLogger blacklistLogger = new BlacklistLogger();
/**
* Last event.
*/
private BlacklistEvent lastEvent;
/**
* Used to prevent flooding.
*/
Map<String,BlacklistTrackedEvent> lastAffected =
new HashMap<String,BlacklistTrackedEvent>();
private boolean useAsWhitelist;
private final Logger logger;
public Blacklist(Boolean useAsWhitelist, Logger logger) {
this.useAsWhitelist = useAsWhitelist;
this.logger = logger;
}
/**
* Returns whether the list is empty.
*
* @return whether the blacklist is empty
*/
public boolean isEmpty() {
return blacklist.isEmpty();
}
/**
* Get the entries for an item or list.
*
* @param id The item id to get blacklist information for
* @return The blacklist entries for {@code id}
*/
public List<BlacklistEntry> getEntries(int id) {
return blacklist.get(id);
}
/**
* Get the number of individual items that have blacklist entries.
*
* @return The number of items in the blacklist
*/
public int getItemCount() {
return blacklist.size();
}
/**
* Returns whether the blacklist is used as a whitelist.
*
* @return whether the blacklist is be used as a whitelist
*/
public boolean isWhitelist() {
return useAsWhitelist;
}
/**
* Get the logger.
*
* @return The logger used in this blacklist
*/
public BlacklistLogger getLogger() {
return blacklistLogger;
}
/**
* Method to handle the event.
*
* @param event The event to check
* @param forceRepeat Whether to force quickly repeating notifications
* @param silent Whether to force-deny notifications
* @return Whether the event is allowed
*/
public boolean check(BlacklistEvent event, boolean forceRepeat, boolean silent) {
List<BlacklistEntry> entries = getEntries(event.getType());
if (entries == null) {
return true;
}
boolean ret = true;
for (BlacklistEntry entry : entries) {
if (!entry.check(useAsWhitelist, event, forceRepeat, silent)) {
ret = false;
}
}
return ret;
}
/**
* Load the blacklist.
*
* @param file The file to load from
* @throws IOException if an error occurred reading from the file
*/
public void load(File file) throws IOException {
FileReader input = null;
Map<Integer,List<BlacklistEntry>> blacklist =
new HashMap<Integer,List<BlacklistEntry>>();
try {
input = new FileReader(file);
BufferedReader buff = new BufferedReader(input);
String line;
List<BlacklistEntry> currentEntries = null;
while ((line = buff.readLine()) != null) {
line = line.trim();
// Blank line
if (line.length() == 0) {
continue;
} else if (line.charAt(0) == ';' || line.charAt(0) == '#') {
continue;
}
if (line.matches("^\\[.*\\]$")) {
String[] items = line.substring(1, line.length() - 1).split(",");
currentEntries = new ArrayList<BlacklistEntry>();
for (String item : items) {
int id;
try {
id = Integer.parseInt(item.trim());
} catch (NumberFormatException e) {
id = getItemID(item.trim());
if (id == 0) {
logger.log(Level.WARNING, "Unknown block name: "
+ item);
break;
}
}
BlacklistEntry entry = new BlacklistEntry(this);
if (blacklist.containsKey(id)) {
blacklist.get(id).add(entry);
} else {
List<BlacklistEntry> entries = new ArrayList<BlacklistEntry>();
entries.add(entry);
blacklist.put(id, entries);
}
currentEntries.add(entry);
}
} else if (currentEntries != null) {
String[] parts = line.split("=");
if (parts.length == 1) {
logger.log(Level.WARNING, "Found option with no value "
+ file.getName() + " for '" + line + "'");
continue;
}
boolean unknownOption = false;
for (BlacklistEntry entry : currentEntries) {
if (parts[0].equalsIgnoreCase("ignore-groups")) {
entry.setIgnoreGroups(parts[1].split(","));
} else if (parts[0].equalsIgnoreCase("ignore-perms")) {
entry.setIgnorePermissions(parts[1].split(","));
} else if (parts[0].equalsIgnoreCase("on-break")) {
entry.setBreakActions(parts[1].split(","));
} else if (parts[0].equalsIgnoreCase("on-destroy-with")) {
entry.setDestroyWithActions(parts[1].split(","));
} else if (parts[0].equalsIgnoreCase("on-place")) {
entry.setPlaceActions(parts[1].split(","));
} else if (parts[0].equalsIgnoreCase("on-interact")) {
entry.setInteractActions(parts[1].split(","));
} else if (parts[0].equalsIgnoreCase("on-use")) {
entry.setUseActions(parts[1].split(","));
} else if (parts[0].equalsIgnoreCase("on-drop")) {
entry.setDropActions(parts[1].split(","));
} else if (parts[0].equalsIgnoreCase("on-acquire")) {
entry.setAcquireActions(parts[1].split(","));
} else if (parts[0].equalsIgnoreCase("message")) {
entry.setMessage(parts[1].trim());
} else if (parts[0].equalsIgnoreCase("comment")) {
entry.setComment(parts[1].trim());
} else {
unknownOption = true;
}
}
if (unknownOption) {
logger.log(Level.WARNING, "Unknown option '" + parts[0]
+ "' in " + file.getName() + " for '" + line + "'");
}
} else {
logger.log(Level.WARNING, "Found option with no heading "
+ file.getName() + " for '" + line + "'");
}
}
this.blacklist = blacklist;
} finally {
try {
if (input != null) {
input.close();
}
} catch (IOException ignore) {
}
}
}
/**
* Get the last event.
*
* @return The last event
*/
public BlacklistEvent getLastEvent() {
return lastEvent;
}
/**
* Notify administrators.
*
* @param event The event to notify about
* @param comment The comment to notify with
*/
public void notify(BlacklistEvent event, String comment) {
lastEvent = event;
broadcastNotification(ChatColor.GRAY + "WG: "
+ ChatColor.LIGHT_PURPLE + event.getPlayer().getName()
+ ChatColor.GOLD + " (" + event.getDescription() + ") "
+ ChatColor.WHITE
+ getFriendlyItemName(event.getType())
+ (comment != null ? " (" + comment + ")" : "") + ".");
}
/**
* Sends a notification to all subscribing users.
*
* @param msg The message to broadcast
*/
public abstract void broadcastNotification(String msg);
/**
* Forget a player.
*
* @param player The player to forget
*/
public void forgetPlayer(LocalPlayer player) {
lastAffected.remove(player.getName());
}
/**
* Forget all players.
*/
public void forgetAllPlayers() {
lastAffected.clear();
}
/**
* Get an item's ID from its name.
*
* @param name the name of the item to look up
* @return the id for name if contained in ItemId, else -1
*/
private static int getItemID(String name) {
ItemType type = ItemType.lookup(name);
if (type != null) {
return type.getID();
} else {
return -1;
}
}
/**
* Get an item's friendly name with its ID.
*
* @param id The id to look up
* @return The item's friendly name
*/
private static String getFriendlyItemName(int id) {
ItemType type = ItemType.fromID(id);
if (type != null) {
return type.getName() + " (#" + id + ")";
} else {
return "#" + id + "";
}
}
}
@@ -0,0 +1,424 @@
// $Id$
/*
* WorldGuard
* Copyright (C) 2010 sk89q <http://www.sk89q.com>
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU 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 General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package com.sk89q.worldguard.blacklist;
import java.util.Collections;
import java.util.HashSet;
import java.util.Set;
import org.bukkit.ChatColor;
import com.sk89q.worldedit.blocks.ItemType;
import com.sk89q.worldguard.LocalPlayer;
import com.sk89q.worldguard.blacklist.events.BlacklistEvent;
import com.sk89q.worldguard.blacklist.events.BlockBreakBlacklistEvent;
import com.sk89q.worldguard.blacklist.events.BlockInteractBlacklistEvent;
import com.sk89q.worldguard.blacklist.events.BlockPlaceBlacklistEvent;
import com.sk89q.worldguard.blacklist.events.DestroyWithBlacklistEvent;
import com.sk89q.worldguard.blacklist.events.ItemAcquireBlacklistEvent;
import com.sk89q.worldguard.blacklist.events.ItemDropBlacklistEvent;
import com.sk89q.worldguard.blacklist.events.ItemUseBlacklistEvent;
/**
*
* @author sk89q
*/
public class BlacklistEntry {
/**
* Parent blacklist entry.
*/
private Blacklist blacklist;
/**
* List of groups to not affect.
*/
private Set<String> ignoreGroups;
/**
* List of permissions to not affect.
*/
private Set<String> ignorePermissions;
private String[] breakActions;
private String[] destroyWithActions;
private String[] placeActions;
private String[] interactActions;
private String[] useActions;
private String[] dropActions;
private String[] acquireActions;
private String message;
private String comment;
/**
* Construct the object.
*
* @param blacklist The blacklist that contains this entry
*/
public BlacklistEntry(Blacklist blacklist) {
this.blacklist = blacklist;
}
/**
* @return the ignoreGroups
*/
public String[] getIgnoreGroups() {
return ignoreGroups.toArray(new String[ignoreGroups.size()]);
}
/**
* @return the ignoreGroups
*/
public String[] getIgnorePermissions() {
return ignorePermissions.toArray(new String[ignorePermissions.size()]);
}
/**
* @param ignoreGroups the ignoreGroups to set
*/
public void setIgnoreGroups(String[] ignoreGroups) {
Set<String> ignoreGroupsSet = new HashSet<String>();
for (String group : ignoreGroups) {
ignoreGroupsSet.add(group.toLowerCase());
}
this.ignoreGroups = ignoreGroupsSet;
}
/**
* @param ignorePermissions the ignorePermissions to set
*/
public void setIgnorePermissions(String[] ignorePermissions) {
Set<String> ignorePermissionsSet = new HashSet<String>();
Collections.addAll(ignorePermissionsSet, ignorePermissions);
this.ignorePermissions = ignorePermissionsSet;
}
/**
* @return The actions that occur when breaking
*/
public String[] getBreakActions() {
return breakActions;
}
/**
* @param actions The actions to occur when breaking
*/
public void setBreakActions(String[] actions) {
this.breakActions = actions;
}
/**
* @return The actions that occur when destroying with a specific item
*/
public String[] getDestroyWithActions() {
return destroyWithActions;
}
/**
* @param actions The actions to occur when destroying with an item
*/
public void setDestroyWithActions(String[] actions) {
this.destroyWithActions = actions;
}
/**
* @return The actions that will occur when placing
*/
public String[] getPlaceActions() {
return placeActions;
}
/**
* @param actions The actions to occur when placing
*/
public void setPlaceActions(String[] actions) {
this.placeActions = actions;
}
/**
* @return The actions that will occur when interacting
*/
public String[] getInteractActions() {
return interactActions;
}
/**
* @param actions The actions to occur when interacting
*/
public void setInteractActions(String[] actions) {
this.interactActions = actions;
}
/**
* @return The actions that will occur when using
*/
public String[] getUseActions() {
return useActions;
}
/**
* @param actions The actions to occur when using
*/
public void setUseActions(String[] actions) {
this.useActions = actions;
}
/**
* @return The actions that will occur when dropping
*/
public String[] getDropActions() {
return dropActions;
}
/**
* @param actions The actions to occur when dropping
*/
public void setDropActions(String[] actions) {
this.dropActions = actions;
}
/**
* @return The actions that will occur when acquiring
*/
public String[] getAcquireActions() {
return acquireActions;
}
/**
* @param actions The actions to occur when acquiring
*/
public void setAcquireActions(String[] actions) {
this.acquireActions = actions;
}
/**
* @return the message
*/
public String getMessage() {
return message;
}
/**
* @param message the message to set
*/
public void setMessage(String message) {
this.message = message;
}
/**
* @return the comment
*/
public String getComment() {
return comment;
}
/**
* @param comment the comment to set
*/
public void setComment(String comment) {
this.comment = comment;
}
/**
* Returns true if this player should be ignored.
*
* @param player The player to check
* @return whether this player should be ignored for blacklist blocking
*/
public boolean shouldIgnore(LocalPlayer player) {
if (ignoreGroups != null) {
for (String group : player.getGroups()) {
if (ignoreGroups.contains(group.toLowerCase())) {
return true;
}
}
}
if (ignorePermissions != null) {
for (String perm : ignorePermissions) {
if (player.hasPermission(perm)) {
return true;
}
}
}
return false;
}
/**
* Get the associated actions with an event.
*
* @param event The event to check
* @return The actions for the given event
*/
private String[] getActions(BlacklistEvent event) {
if (event instanceof BlockBreakBlacklistEvent) {
return breakActions;
} else if (event instanceof BlockPlaceBlacklistEvent) {
return placeActions;
} else if (event instanceof BlockInteractBlacklistEvent) {
return interactActions;
} else if (event instanceof DestroyWithBlacklistEvent) {
return destroyWithActions;
} else if (event instanceof ItemAcquireBlacklistEvent) {
return acquireActions;
} else if (event instanceof ItemDropBlacklistEvent) {
return dropActions;
} else if (event instanceof ItemUseBlacklistEvent) {
return useActions;
} else {
return null;
}
}
/**
* Method to handle the event.
*
* @param useAsWhitelist Whether this entry is buing used in a whitelist
* @param event The event to check
* @param forceRepeat Whether to force repeating notifications even within the delay limit
* @param silent Whether to prevent notifications from happening
* @return Whether the action was allowed
*/
public boolean check(boolean useAsWhitelist, BlacklistEvent event, boolean forceRepeat, boolean silent) {
LocalPlayer player = event.getPlayer();
if (shouldIgnore(player)) {
return true;
}
String name = player.getName();
long now = System.currentTimeMillis();
boolean repeating = false;
// Check to see whether this event is being repeated
BlacklistTrackedEvent tracked = blacklist.lastAffected.get(name);
if (tracked != null) {
if (tracked.matches(event, now)) {
repeating = true;
}
} else {
blacklist.lastAffected.put(name, new BlacklistTrackedEvent(event, now));
}
String actions[] = getActions(event);
boolean ret = !useAsWhitelist;
// Nothing to do
if (actions == null) {
return ret;
}
for (String action : actions) {
// Deny
if (action.equalsIgnoreCase("deny")) {
if (silent) {
return false;
}
ret = false;
// Allow
} else if (action.equalsIgnoreCase("allow")) {
if (silent) {
return true;
}
ret = true;
// Kick
} else if (action.equalsIgnoreCase("kick")) {
if (silent) {
continue;
}
if (this.message != null) {
player.kick(String.format(this.message,
getFriendlyItemName(event.getType())));
} else {
player.kick("You can't " + event.getDescription() + " "
+ getFriendlyItemName(event.getType()));
}
// Ban
} else if (action.equalsIgnoreCase("ban")) {
if (silent) {
continue;
}
if (this.message != null) {
player.ban("Banned: " + String.format(this.message,
getFriendlyItemName(event.getType())));
} else {
player.ban("Banned: You can't "
+ event.getDescription() + " "
+ getFriendlyItemName(event.getType()));
}
} else if (!silent && (!repeating || forceRepeat)) {
// Notify
if (action.equalsIgnoreCase("notify")) {
blacklist.notify(event, comment);
// Log
} else if (action.equalsIgnoreCase("log")) {
blacklist.getLogger().logEvent(event, comment);
// Tell
} else if (action.equalsIgnoreCase("tell")) {
if (this.message != null) {
player.printRaw(ChatColor.YELLOW +
String.format(message, getFriendlyItemName(event.getType()))
+ ".");
} else {
player.printRaw(ChatColor.YELLOW + "You're not allowed to "
+ event.getDescription() + " "
+ getFriendlyItemName(event.getType()) + ".");
}
}
}
}
return ret;
}
/**
* Get an item's friendly name with its ID.
*
* @param id The id to get a name for
*/
private static String getFriendlyItemName(int id) {
ItemType type = ItemType.fromID(id);
if (type != null) {
return type.getName() + " (#" + id + ")";
} else {
return "#" + id + "";
}
}
}
@@ -1,44 +1,47 @@
// $Id$
/*
* WorldGuard, a suite of tools for Minecraft
* Copyright (C) sk89q <http://www.sk89q.com>
* Copyright (C) WorldGuard team and contributors
* WorldGuard
* Copyright (C) 2010 sk89q <http://www.sk89q.com>
*
* 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
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU 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.
* 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 General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
*/
package com.sk89q.worldguard.blacklist;
import com.sk89q.worldguard.blacklist.event.BlacklistEvent;
import com.sk89q.worldguard.blacklist.logger.LoggerHandler;
import java.util.HashSet;
import java.util.Set;
public class BlacklistLoggerHandler implements LoggerHandler {
import com.sk89q.worldguard.blacklist.events.BlacklistEvent;
import com.sk89q.worldguard.blacklist.loggers.BlacklistLoggerHandler;
/**
*
* @author sk89q
*/
public class BlacklistLogger implements BlacklistLoggerHandler {
/**
* List of logger handlers.
*/
private Set<LoggerHandler> handlers
= new HashSet<>();
private Set<BlacklistLoggerHandler> handlers
= new HashSet<BlacklistLoggerHandler>();
/**
* Add a handler.
*
* @param handler The handler to add
*/
public void addHandler(LoggerHandler handler) {
public void addHandler(BlacklistLoggerHandler handler) {
handlers.add(handler);
}
@@ -47,7 +50,7 @@ public class BlacklistLoggerHandler implements LoggerHandler {
*
* @param handler The handler to remove
*/
public void removeHandler(LoggerHandler handler) {
public void removeHandler(BlacklistLoggerHandler handler) {
handlers.remove(handler);
}
@@ -63,9 +66,8 @@ public class BlacklistLoggerHandler implements LoggerHandler {
*
* @param event The event to log
*/
@Override
public void logEvent(BlacklistEvent event, String comment) {
for (LoggerHandler handler : handlers) {
for (BlacklistLoggerHandler handler : handlers) {
handler.logEvent(event, comment);
}
}
@@ -73,11 +75,9 @@ public class BlacklistLoggerHandler implements LoggerHandler {
/**
* Close the connection.
*/
@Override
public void close() {
for (LoggerHandler handler : handlers) {
for (BlacklistLoggerHandler handler : handlers) {
handler.close();
}
}
}
@@ -0,0 +1,48 @@
// $Id$
/*
* WorldGuard
* Copyright (C) 2010 sk89q <http://www.sk89q.com>
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU 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 General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package com.sk89q.worldguard.blacklist;
import com.sk89q.worldguard.blacklist.events.BlacklistEvent;
/**
*
* @author sk89q
*/
public class BlacklistTrackedEvent {
private BlacklistEvent event;
private long time;
/**
* Construct the object.
*
* @param event The event tracked
* @param time The time at which the event occurred
*/
public BlacklistTrackedEvent(BlacklistEvent event, long time) {
this.event = event;
this.time = time;
}
public boolean matches(BlacklistEvent other, long now) {
return other.getType() == event.getType()
&& time > now - 3000
&& other.getClass() == event.getClass();
}
}
@@ -0,0 +1,85 @@
// $Id$
/*
* WorldGuard
* Copyright (C) 2010 sk89q <http://www.sk89q.com>
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU 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 General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package com.sk89q.worldguard.blacklist.events;
import com.sk89q.worldedit.Vector;
import com.sk89q.worldguard.LocalPlayer;
/**
* Represents a blacklist event.
*
* @author sk89q
*/
public abstract class BlacklistEvent {
private Vector pos;
private int type;
/**
* Holds the player that triggered the event.
*/
private LocalPlayer player;
/**
* Construct the object.
*
* @param player The player associated with this event
* @param pos The position the event occurred at
* @param type The type of item used
*/
public BlacklistEvent(LocalPlayer player, Vector pos, int type) {
this.player = player;
this.pos = pos;
this.type = type;
}
/**
* Get the player.
*
* @return The player associated with this event
*/
public LocalPlayer getPlayer() {
return player;
}
/**
* Get the position.
*
* @return The position of this event
*/
public Vector getPosition() {
return pos;
}
/**
* Get the item type.
*
* @return The type associated with this event
*/
public int getType() {
return type;
}
/**
* Get a short description such as "break" or "destroy with."
*
* @return The event description
*/
public abstract String getDescription();
}
@@ -0,0 +1,29 @@
// $Id$
/*
* WorldGuard
* Copyright (C) 2010 sk89q <http://www.sk89q.com>
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU 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 General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package com.sk89q.worldguard.blacklist.events;
import com.sk89q.worldedit.Vector;
import com.sk89q.worldguard.LocalPlayer;
public abstract class BlockBlacklistEvent extends BlacklistEvent {
public BlockBlacklistEvent(LocalPlayer player, Vector pos, int type) {
super(player, pos, type);
}
}
@@ -0,0 +1,34 @@
// $Id$
/*
* WorldGuard
* Copyright (C) 2010 sk89q <http://www.sk89q.com>
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU 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 General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package com.sk89q.worldguard.blacklist.events;
import com.sk89q.worldedit.Vector;
import com.sk89q.worldguard.LocalPlayer;
public class BlockBreakBlacklistEvent extends BlockBlacklistEvent {
public BlockBreakBlacklistEvent(LocalPlayer player, Vector pos, int type) {
super(player, pos, type);
}
@Override
public String getDescription() {
return "break";
}
}
@@ -0,0 +1,34 @@
// $Id$
/*
* WorldGuard
* Copyright (C) 2010 sk89q <http://www.sk89q.com>
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU 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 General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package com.sk89q.worldguard.blacklist.events;
import com.sk89q.worldedit.Vector;
import com.sk89q.worldguard.LocalPlayer;
public class BlockInteractBlacklistEvent extends BlockBlacklistEvent {
public BlockInteractBlacklistEvent(LocalPlayer player, Vector pos, int type) {
super(player, pos, type);
}
@Override
public String getDescription() {
return "interact with";
}
}
@@ -0,0 +1,34 @@
// $Id$
/*
* WorldGuard
* Copyright (C) 2010 sk89q <http://www.sk89q.com>
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU 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 General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package com.sk89q.worldguard.blacklist.events;
import com.sk89q.worldedit.Vector;
import com.sk89q.worldguard.LocalPlayer;
public class BlockPlaceBlacklistEvent extends BlockBlacklistEvent {
public BlockPlaceBlacklistEvent(LocalPlayer player, Vector pos, int type) {
super(player, pos, type);
}
@Override
public String getDescription() {
return "place";
}
}
@@ -0,0 +1,34 @@
// $Id$
/*
* WorldGuard
* Copyright (C) 2010 sk89q <http://www.sk89q.com>
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU 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 General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package com.sk89q.worldguard.blacklist.events;
import com.sk89q.worldedit.Vector;
import com.sk89q.worldguard.LocalPlayer;
public class DestroyWithBlacklistEvent extends BlacklistEvent {
public DestroyWithBlacklistEvent(LocalPlayer player, Vector pos, int type) {
super(player, pos, type);
}
@Override
public String getDescription() {
return "destroy with";
}
}
@@ -0,0 +1,34 @@
// $Id$
/*
* WorldGuard
* Copyright (C) 2010 sk89q <http://www.sk89q.com>
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU 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 General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package com.sk89q.worldguard.blacklist.events;
import com.sk89q.worldedit.Vector;
import com.sk89q.worldguard.LocalPlayer;
public class ItemAcquireBlacklistEvent extends ItemBlacklistEvent {
public ItemAcquireBlacklistEvent(LocalPlayer player, Vector pos, int type) {
super(player, pos, type);
}
@Override
public String getDescription() {
return "acquire";
}
}
@@ -0,0 +1,29 @@
// $Id$
/*
* WorldGuard
* Copyright (C) 2010 sk89q <http://www.sk89q.com>
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU 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 General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package com.sk89q.worldguard.blacklist.events;
import com.sk89q.worldedit.Vector;
import com.sk89q.worldguard.LocalPlayer;
public abstract class ItemBlacklistEvent extends BlacklistEvent {
public ItemBlacklistEvent(LocalPlayer player, Vector pos, int type) {
super(player, pos, type);
}
}
@@ -0,0 +1,34 @@
// $Id$
/*
* WorldGuard
* Copyright (C) 2010 sk89q <http://www.sk89q.com>
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU 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 General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package com.sk89q.worldguard.blacklist.events;
import com.sk89q.worldedit.Vector;
import com.sk89q.worldguard.LocalPlayer;
public class ItemDropBlacklistEvent extends ItemBlacklistEvent {
public ItemDropBlacklistEvent(LocalPlayer player, Vector pos, int type) {
super(player, pos, type);
}
@Override
public String getDescription() {
return "drop";
}
}
@@ -0,0 +1,34 @@
// $Id$
/*
* WorldGuard
* Copyright (C) 2010 sk89q <http://www.sk89q.com>
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU 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 General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package com.sk89q.worldguard.blacklist.events;
import com.sk89q.worldedit.Vector;
import com.sk89q.worldguard.LocalPlayer;
public class ItemUseBlacklistEvent extends ItemBlacklistEvent {
public ItemUseBlacklistEvent(LocalPlayer player, Vector pos, int type) {
super(player, pos, type);
}
@Override
public String getDescription() {
return "use";
}
}
@@ -0,0 +1,42 @@
// $Id$
/*
* WorldGuard
* Copyright (C) 2010 sk89q <http://www.sk89q.com>
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU 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 General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package com.sk89q.worldguard.blacklist.loggers;
import com.sk89q.worldguard.blacklist.events.BlacklistEvent;
/**
* Interface for loggers for the blacklist.
*
* @author sk89q
*/
public interface BlacklistLoggerHandler {
/**
* Log an event.
*
* @param event
* @param comment
*/
public void logEvent(BlacklistEvent event, String comment);
/**
* Close the logger.
*/
public void close();
}
@@ -0,0 +1,128 @@
// $Id$
/*
* WorldGuard
* Copyright (C) 2010 sk89q <http://www.sk89q.com>
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU 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 General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package com.sk89q.worldguard.blacklist.loggers;
import java.util.logging.Level;
import java.util.logging.Logger;
import com.sk89q.worldedit.blocks.ItemType;
import com.sk89q.worldguard.blacklist.events.BlacklistEvent;
import com.sk89q.worldguard.blacklist.events.BlockBreakBlacklistEvent;
import com.sk89q.worldguard.blacklist.events.BlockInteractBlacklistEvent;
import com.sk89q.worldguard.blacklist.events.BlockPlaceBlacklistEvent;
import com.sk89q.worldguard.blacklist.events.DestroyWithBlacklistEvent;
import com.sk89q.worldguard.blacklist.events.ItemAcquireBlacklistEvent;
import com.sk89q.worldguard.blacklist.events.ItemDropBlacklistEvent;
import com.sk89q.worldguard.blacklist.events.ItemUseBlacklistEvent;
/**
*
* @author sk89q
*/
public class ConsoleLoggerHandler implements BlacklistLoggerHandler {
private String worldName;
private final Logger logger;
public ConsoleLoggerHandler(String worldName, Logger logger) {
this.worldName = worldName;
this.logger = logger;
}
public void logEvent(BlacklistEvent event, String comment) {
// Block break
if (event instanceof BlockBreakBlacklistEvent) {
BlockBreakBlacklistEvent evt = (BlockBreakBlacklistEvent)event;
logger.log(Level.INFO, "[" + worldName + "] " + event.getPlayer().getName()
+ " tried to break " + getFriendlyItemName(evt.getType())
+ (comment != null ? " (" + comment + ")" : ""));
// Block place
} else if (event instanceof BlockPlaceBlacklistEvent) {
BlockPlaceBlacklistEvent evt = (BlockPlaceBlacklistEvent)event;
logger.log(Level.INFO, "[" + worldName + "] " + event.getPlayer().getName()
+ " tried to place " + getFriendlyItemName(evt.getType())
+ (comment != null ? " (" + comment + ")" : ""));
// Block interact
} else if (event instanceof BlockInteractBlacklistEvent) {
BlockInteractBlacklistEvent evt = (BlockInteractBlacklistEvent)event;
logger.log(Level.INFO, "[" + worldName + "] " + event.getPlayer().getName()
+ " tried to interact with " + getFriendlyItemName(evt.getType())
+ (comment != null ? " (" + comment + ")" : ""));
// Destroy with
} else if (event instanceof DestroyWithBlacklistEvent) {
DestroyWithBlacklistEvent evt = (DestroyWithBlacklistEvent)event;
logger.log(Level.INFO, "[" + worldName + "] " + event.getPlayer().getName()
+ " tried to destroy with " + getFriendlyItemName(evt.getType())
+ (comment != null ? " (" + comment + ")" : ""));
// Acquire
} else if (event instanceof ItemAcquireBlacklistEvent) {
ItemAcquireBlacklistEvent evt = (ItemAcquireBlacklistEvent)event;
logger.log(Level.INFO, "[" + worldName + "] " + event.getPlayer().getName()
+ " tried to acquire " + getFriendlyItemName(evt.getType())
+ (comment != null ? " (" + comment + ")" : ""));
// Drop
} else if (event instanceof ItemDropBlacklistEvent) {
ItemDropBlacklistEvent evt = (ItemDropBlacklistEvent)event;
logger.log(Level.INFO, "[" + worldName + "] " + event.getPlayer().getName()
+ " tried to drop " + getFriendlyItemName(evt.getType())
+ (comment != null ? " (" + comment + ")" : ""));
// Use
} else if (event instanceof ItemUseBlacklistEvent) {
ItemUseBlacklistEvent evt = (ItemUseBlacklistEvent)event;
logger.log(Level.INFO, "[" + worldName + "] " + event.getPlayer().getName()
+ " tried to use " + getFriendlyItemName(evt.getType())
+ (comment != null ? " (" + comment + ")" : ""));
// Unknown
} else {
logger.log(Level.INFO, "[" + worldName + "] " + event.getPlayer().getName()
+ " caught unknown event: " + event.getClass().getCanonicalName());
}
}
/**
* Get an item's friendly name with its ID.
*
* @param id The item id
* @return The friendly name of the item
*/
private static String getFriendlyItemName(int id) {
ItemType type = ItemType.fromID(id);
if (type != null) {
return type.getName() + " (#" + id + ")";
} else {
return "#" + id;
}
}
/**
* Close the connection.
*/
public void close() {
}
}
@@ -0,0 +1,205 @@
// $Id$
/*
* WorldGuard
* Copyright (C) 2010 sk89q <http://www.sk89q.com>
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU 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 General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package com.sk89q.worldguard.blacklist.loggers;
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.PreparedStatement;
import java.sql.SQLException;
import java.util.logging.Level;
import java.util.logging.Logger;
import com.sk89q.worldedit.Vector;
import com.sk89q.worldguard.LocalPlayer;
import com.sk89q.worldguard.blacklist.events.BlacklistEvent;
import com.sk89q.worldguard.blacklist.events.BlockBreakBlacklistEvent;
import com.sk89q.worldguard.blacklist.events.BlockPlaceBlacklistEvent;
import com.sk89q.worldguard.blacklist.events.BlockInteractBlacklistEvent;
import com.sk89q.worldguard.blacklist.events.DestroyWithBlacklistEvent;
import com.sk89q.worldguard.blacklist.events.ItemAcquireBlacklistEvent;
import com.sk89q.worldguard.blacklist.events.ItemDropBlacklistEvent;
import com.sk89q.worldguard.blacklist.events.ItemUseBlacklistEvent;
/**
*
* @author sk89q
*/
public class DatabaseLoggerHandler implements BlacklistLoggerHandler {
/**
* DSN.
*/
private final String dsn;
/**
* Username.
*/
private final String user;
/**
* Password.
*/
private final String pass;
/**
* Table.
*/
private final String table;
/**
* World name.
*/
private final String worldName;
/**
* Database connection.
*/
private Connection conn;
private final Logger logger;
/**
* Construct the object.
*
* @param dsn The DSN for the connection
* @param user The username to connect with
* @param pass The password to connect with
* @param table The table to log to
* @param worldName The name of the world to log
* @param logger The logger to log errors to
*/
public DatabaseLoggerHandler(String dsn, String user, String pass, String table, String worldName, Logger logger) {
this.dsn = dsn;
this.user = user;
this.pass = pass;
this.table = table;
this.worldName = worldName;
this.logger = logger;
}
/**
* Gets the database connection.
*
* @return The database connection
* @throws SQLException when the connection cannot be created
*/
private Connection getConnection() throws SQLException {
if (conn == null || conn.isClosed()) {
conn = DriverManager.getConnection(dsn, user, pass);
}
return conn;
}
/**
* Log an event to the database.
*
* @param event The event to log
* @param player The player associated with the event
* @param pos The location of the event
* @param item The item used
* @param comment The comment associated with the event
*/
private void logEvent(String event, LocalPlayer player, Vector pos, int item,
String comment) {
try {
Connection conn = getConnection();
PreparedStatement stmt = conn.prepareStatement(
"INSERT INTO " + table
+ "(event, world, player, x, y, z, item, time, comment) VALUES "
+ "(?, ?, ?, ?, ?, ?, ?, ?, ?)");
stmt.setString(1, event);
stmt.setString(2, worldName);
stmt.setString(3, player.getName());
stmt.setInt(4, pos.getBlockX());
stmt.setInt(5, pos.getBlockY());
stmt.setInt(6, pos.getBlockZ());
stmt.setInt(7, item);
stmt.setInt(8, (int)(System.currentTimeMillis() / 1000));
stmt.setString(9, comment);
stmt.executeUpdate();
} catch (SQLException e) {
logger.log(Level.SEVERE, "Failed to log blacklist event to database: "
+ e.getMessage());
}
}
/**
* Log an event.
*
* @param event The event to log
*/
public void logEvent(BlacklistEvent event, String comment) {
// Block break
if (event instanceof BlockBreakBlacklistEvent) {
BlockBreakBlacklistEvent evt = (BlockBreakBlacklistEvent)event;
logEvent("BREAK", evt.getPlayer(), evt.getPosition(),
evt.getType(), comment);
// Block place
} else if (event instanceof BlockPlaceBlacklistEvent) {
BlockPlaceBlacklistEvent evt = (BlockPlaceBlacklistEvent)event;
logEvent("PLACE", evt.getPlayer(), evt.getPosition(),
evt.getType(), comment);
// Block interact
} else if (event instanceof BlockInteractBlacklistEvent) {
BlockInteractBlacklistEvent evt = (BlockInteractBlacklistEvent)event;
logEvent("INTERACT", evt.getPlayer(), evt.getPosition(),
evt.getType(), comment);
// Destroy with
} else if (event instanceof DestroyWithBlacklistEvent) {
DestroyWithBlacklistEvent evt = (DestroyWithBlacklistEvent)event;
logEvent("DESTROY_WITH", evt.getPlayer(), evt.getPosition(),
evt.getType(), comment);
// Acquire
} else if (event instanceof ItemAcquireBlacklistEvent) {
ItemAcquireBlacklistEvent evt = (ItemAcquireBlacklistEvent)event;
logEvent("ACQUIRE", evt.getPlayer(), evt.getPlayer().getPosition(),
evt.getType(), comment);
// Drop
} else if (event instanceof ItemDropBlacklistEvent) {
ItemDropBlacklistEvent evt = (ItemDropBlacklistEvent)event;
logEvent("DROP", evt.getPlayer(), evt.getPlayer().getPosition(),
evt.getType(), comment);
// Use
} else if (event instanceof ItemUseBlacklistEvent) {
ItemUseBlacklistEvent evt = (ItemUseBlacklistEvent)event;
logEvent("USE", evt.getPlayer(), evt.getPlayer().getPosition(),
evt.getType(), comment);
// Unknown
} else {
logEvent("UNKNOWN", event.getPlayer(), event.getPlayer().getPosition(),
-1, comment);
}
}
/**
* Close the connection.
*/
public void close() {
try {
if (conn != null && !conn.isClosed()) {
conn.close();
}
} catch (SQLException ignore) {
}
}
}
@@ -1,28 +1,23 @@
// $Id$
/*
* WorldGuard, a suite of tools for Minecraft
* Copyright (C) sk89q <http://www.sk89q.com>
* Copyright (C) WorldGuard team and contributors
* WorldGuard
* Copyright (C) 2010 sk89q <http://www.sk89q.com>
*
* 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
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU 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.
* 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 General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
*/
package com.sk89q.worldguard.blacklist.logger;
import com.sk89q.worldedit.math.BlockVector3;
import com.sk89q.worldguard.LocalPlayer;
import com.sk89q.worldguard.blacklist.event.BlacklistEvent;
import com.sk89q.worldguard.blacklist.target.Target;
package com.sk89q.worldguard.blacklist.loggers;
import java.io.BufferedWriter;
import java.io.File;
@@ -40,26 +35,54 @@ import java.util.logging.Logger;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
public class FileHandler implements LoggerHandler {
import com.sk89q.worldedit.Vector;
import com.sk89q.worldedit.blocks.ItemType;
import com.sk89q.worldguard.LocalPlayer;
import com.sk89q.worldguard.blacklist.events.BlacklistEvent;
/**
*
* @author sk89q
*/
public class FileLoggerHandler implements BlacklistLoggerHandler {
/**
* Regex for patterns in the path.
*/
private static Pattern pattern = Pattern.compile("%.");
private static SimpleDateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
/**
* Date format.
*/
private static SimpleDateFormat dateFormat =
new SimpleDateFormat("yyyyy-MM-dd HH:mm:ss");
/**
* Number of files to keep open at a time.
*/
private int cacheSize = 10;
/**
* Path pattern.
*/
private String pathPattern;
/**
* World name.
*/
private String worldName;
private TreeMap<String,LogFileWriter> writers = new TreeMap<>();
/**
* Cache of writers.
*/
private TreeMap<String,FileLoggerWriter> writers =
new TreeMap<String,FileLoggerWriter>();
private final Logger logger;
/**
* Construct the object.
*
* @param pathPattern The pattern for the log file path
* @param pathPattern The pattern for the logflie path
* @param worldName The name of the world
* @param logger The logger used to log errors
*/
public FileHandler(String pathPattern, String worldName, Logger logger) {
public FileLoggerHandler(String pathPattern, String worldName, Logger logger) {
this.pathPattern = pathPattern;
this.worldName = worldName;
this.logger = logger;
@@ -73,7 +96,7 @@ public class FileHandler implements LoggerHandler {
* @param worldName The name of the associated world
* @param logger The logger to log errors with
*/
public FileHandler(String pathPattern, int cacheSize, String worldName, Logger logger) {
public FileLoggerHandler(String pathPattern, int cacheSize, String worldName, Logger logger) {
if (cacheSize < 1) {
throw new IllegalArgumentException("Cache size cannot be less than 1");
}
@@ -86,7 +109,7 @@ public class FileHandler implements LoggerHandler {
/**
* Build the path.
*
* @param playerName The name of the player
* @param playerName The name of the playername
* @return The path for the logfile
*/
private String buildPath(String playerName) {
@@ -155,7 +178,7 @@ public class FileHandler implements LoggerHandler {
String line = "[" + date + "] " + player.getName() + ": " + message
+ (comment != null ? " (" + comment + ")" : "") + "\r\n";
LogFileWriter writer = writers.get(path);
FileLoggerWriter writer = writers.get(path);
// Writer already exists!
if (writer != null) {
@@ -181,17 +204,17 @@ public class FileHandler implements LoggerHandler {
BufferedWriter out = new BufferedWriter(stream);
out.write(line);
out.flush();
writer = new LogFileWriter(path, out);
writer = new FileLoggerWriter(path, out);
writers.put(path, writer);
// Check to make sure our cache doesn't get too big!
if (writers.size() > cacheSize) {
Iterator<Map.Entry<String,LogFileWriter>> it =
Iterator<Map.Entry<String,FileLoggerWriter>> it =
writers.entrySet().iterator();
// Remove some entries
for (; it.hasNext(); ) {
Map.Entry<String,LogFileWriter> entry = it.next();
Map.Entry<String,FileLoggerWriter> entry = it.next();
try {
entry.getValue().getWriter().close();
} catch (IOException ignore) {
@@ -217,22 +240,44 @@ public class FileHandler implements LoggerHandler {
* @param pos The position to get coordinates for
* @return The position's coordinates in human-readable form
*/
private String getCoordinates(BlockVector3 pos) {
private String getCoordinates(Vector pos) {
return "@" + pos.getBlockX() + "," + pos.getBlockY() + "," + pos.getBlockZ();
}
private void logEvent(BlacklistEvent event, String text, Target target, BlockVector3 pos, String comment) {
log(event.getPlayer(), "Tried to " + text + " " + target.getFriendlyName() + " " + getCoordinates(pos), comment);
private void logEvent(BlacklistEvent event, String text, int id, Vector pos, String comment) {
log(event.getPlayer(), "Tried to " + text + " " + getFriendlyItemName(id)
+ " " + getCoordinates(pos), comment);
}
@Override
/**
* Log an event.
*
* @param event The event to log
*/
public void logEvent(BlacklistEvent event, String comment) {
logEvent(event, event.getDescription(), event.getTarget(), event.getPosition(), comment);
logEvent(event, event.getDescription(), event.getType(), event.getPosition(), comment);
}
@Override
/**
* Get an item's friendly name with its ID.
*
* @param id The id to get a friendly name for
* @return The friendly name
*/
private static String getFriendlyItemName(int id) {
ItemType type = ItemType.fromID(id);
if (type != null) {
return type.getName() + " (#" + id + ")";
} else {
return "#" + id + "";
}
}
/**
* Close handles.
*/
public void close() {
for (Map.Entry<String,LogFileWriter> entry : writers.entrySet()) {
for (Map.Entry<String,FileLoggerWriter> entry : writers.entrySet()) {
try {
entry.getValue().getWriter().close();
} catch (IOException ignore) {
@@ -241,5 +286,4 @@ public class FileHandler implements LoggerHandler {
writers.clear();
}
}
@@ -1,31 +1,42 @@
// $Id$
/*
* WorldGuard, a suite of tools for Minecraft
* Copyright (C) sk89q <http://www.sk89q.com>
* Copyright (C) WorldGuard team and contributors
* WorldGuard
* Copyright (C) 2010 sk89q <http://www.sk89q.com>
*
* 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
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU 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.
* 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 General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
*/
package com.sk89q.worldguard.blacklist.logger;
package com.sk89q.worldguard.blacklist.loggers;
import javax.annotation.Nullable;
import java.io.BufferedWriter;
public class LogFileWriter implements Comparable<LogFileWriter> {
/**
*
* @author sk89q
*/
public class FileLoggerWriter implements Comparable<FileLoggerWriter> {
/**
* Path.
*/
public String path;
/**
* Writer.
*/
private BufferedWriter writer;
/**
* Last use.
*/
private long lastUse;
/**
@@ -34,7 +45,7 @@ public class LogFileWriter implements Comparable<LogFileWriter> {
* @param path The path to write to
* @param writer The writer for the file
*/
public LogFileWriter(String path, BufferedWriter writer) {
public FileLoggerWriter(String path, BufferedWriter writer) {
this.path = path;
this.writer = writer;
lastUse = System.currentTimeMillis();
@@ -70,11 +81,8 @@ public class LogFileWriter implements Comparable<LogFileWriter> {
lastUse = System.currentTimeMillis();
}
@Override
public int compareTo(@Nullable LogFileWriter other) {
if (other == null) {
return 1;
} else if (lastUse > other.lastUse) {
public int compareTo(FileLoggerWriter other) {
if (lastUse > other.lastUse) {
return 1;
} else if (lastUse < other.lastUse) {
return -1;
@@ -82,5 +90,4 @@ public class LogFileWriter implements Comparable<LogFileWriter> {
return 0;
}
}
}
@@ -0,0 +1,36 @@
// $Id$
/*
* WorldGuard
* Copyright (C) 2010 sk89q <http://www.sk89q.com>
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU 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 General Public License for more details.
*
* You should have received a copy of the GNU 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;
public class BukkitBlacklist extends Blacklist {
private WorldGuardPlugin plugin;
public BukkitBlacklist(Boolean useAsWhitelist, WorldGuardPlugin plugin) {
super(useAsWhitelist, plugin.getLogger());
this.plugin = plugin;
}
@Override
public void broadcastNotification(String msg) {
plugin.broadcastNotification(msg);
}
}
@@ -0,0 +1,238 @@
// $Id$
/*
* This file is a part of WorldGuard.
* Copyright (c) sk89q <http://www.sk89q.com>
* Copyright (c) the 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
* (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
* GNU 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 org.bukkit.block.BlockState;
import org.bukkit.entity.Entity;
import org.bukkit.event.Event;
import org.bukkit.inventory.ItemStack;
import com.sk89q.rulelists.Context;
import com.sk89q.worldguard.region.ApplicableRegionSet;
/**
* An implementation of a {@link Context} for Bukkit. This object is thread-safe, but
* the underlying objects returned by this class may not be.
*
* @see Context
*/
public class BukkitContext extends Context {
private final RegionQueryCache regionCache;
private final Event event;
private RegionQuery regionQuery;
private String message;
private Entity sourceEntity;
private Entity targetEntity;
private ItemStack item;
private BlockState sourceBlock;
private BlockState targetBlock;
private BlockState replacedTargetBlock;
private ApplicableRegionSet lastApplRegionSet;
/**
* Construct a context linked to the given event.
*
* @param plugin the WorldGuard plugin
* @param event the event
*/
BukkitContext(WorldGuardPlugin plugin, Event event) {
this.regionCache = plugin.getRegionCache();
this.event = event;
}
/**
* Get the message attribute of this context.
*
* @return message or null
*/
public String getMessage() {
return message;
}
/**
* Set the message attribute of this context.
*
* @param message or null
*/
public void setMessage(String message) {
this.message = message;
}
/**
* Get the source entity for this context. The source entity is the 'cause' of
* this context, if it is available.
*
* @return entity or null
*/
public Entity getSourceEntity() {
return sourceEntity;
}
/**
* Set the source entity for this context. The source entity is the 'cause' of
* this context, if it is available.
*
* @param sourceEntity entity or null
*/
public void setSourceEntity(Entity sourceEntity) {
this.sourceEntity = sourceEntity;
}
/**
* Get the target entity for this context. The target entity is the 'subject'
* of this context, if it is available.
*
* @return entity or null
*/
public Entity getTargetEntity() {
return targetEntity;
}
/**
* Set the target entity for this context. The target entity is the 'subject'
* of this context, if it is available.
*
* @param targetEntity entity or null
*/
public void setTargetEntity(Entity targetEntity) {
this.targetEntity = targetEntity;
}
/**
* Get the primary item related to this context. Only events that are oriented
* around an item have this property set.
*
* @return item or null
*/
public ItemStack getItem() {
return item;
}
/**
* Set the primary item related to this context. Only events that are oriented
* around an item have this property set.
*
* @param item item or null
*/
public void setItem(ItemStack item) {
this.item = item;
}
/**
* Get the source block for this context. The source block is the 'cause'
* of this context, if it is available.
*
* @return block or null
*/
public BlockState getSourceBlock() {
return sourceBlock;
}
/**
* Set the source block for this context. The source block is the 'cause'
* of this context, if it is available.
*
* @param block block or null
*/
public void setSourceBlock(BlockState block) {
this.sourceBlock = block;
}
/**
* Get a target block for this context. The target block is the 'subject' of
* this context, if it is available.
*
* @return block or null
*/
public BlockState getTargetBlock() {
return targetBlock;
}
/**
* Set a target block for this context. The target block is the 'subject' of
* this context, if it is available.
*
* @param targetBlock block or null
*/
public void setTargetBlock(BlockState targetBlock) {
this.targetBlock = targetBlock;
}
/**
* Get the placed block for this context. The placed block is the 'new' block
* that will replace the existing block in this context, if it is available.
*
* @return block or null
*/
public BlockState getPlacedBlock() {
return replacedTargetBlock;
}
/**
* Set the placed block for this context. The placed block is the 'new' block
* that will replace the existing block in this context, if it is available.
*
* @param replacedTargetBlock block or null
*/
public void setPlacedBlock(BlockState replacedTargetBlock) {
this.replacedTargetBlock = replacedTargetBlock;
}
/**
* Get the last {@link ApplicableRegionSet}. This can be set by a rule and used
* within one, but it cannot be guaranteed to exist across rules.
*
* @return an {@link ApplicableRegionSet} or null
*/
public ApplicableRegionSet getApplicableRegionSet() {
return lastApplRegionSet;
}
/**
* Set the last {@link ApplicableRegionSet}.
*
* @param set an {@link ApplicableRegionSet} or null
*/
public void setApplicableRegionSet(ApplicableRegionSet set) {
this.lastApplRegionSet = set;
}
/**
* Get the underlying event object.
*
* @return event object
*/
public Event getEvent() {
return event;
}
/**
* Get the region query object.
*
* @return region query object
*/
public synchronized RegionQuery getRegionQuery() {
if (regionQuery == null) {
regionQuery = regionCache.against(event);
}
return regionQuery;
}
}
@@ -0,0 +1,78 @@
// $Id$
/*
* WorldGuard
* Copyright (C) 2010 sk89q <http://www.sk89q.com>
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU 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 General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package com.sk89q.worldguard.bukkit;
import org.bukkit.Location;
import org.bukkit.entity.Player;
import com.sk89q.worldedit.Vector;
import com.sk89q.worldguard.LocalPlayer;
public class BukkitPlayer extends LocalPlayer {
private Player player;
private WorldGuardPlugin plugin;
public BukkitPlayer(WorldGuardPlugin plugin, Player player) {
this.plugin = plugin;
this.player = player;
}
@Override
public String getName() {
return player.getName();
}
@Override
public boolean hasGroup(String group) {
return plugin.inGroup(player, group);
}
@Override
public Vector getPosition() {
Location loc = player.getLocation();
return new Vector(loc.getX(), loc.getY(), loc.getZ());
}
@Override
public void kick(String msg) {
player.kickPlayer(msg);
}
@Override
public void ban(String msg) {
player.setBanned(true);
player.kickPlayer(msg);
}
@Override
public String[] getGroups() {
return plugin.getGroups(player);
}
@Override
public void printRaw(String msg) {
player.sendMessage(msg);
}
@Override
public boolean hasPermission(String perm) {
return plugin.hasPermission(player, perm);
}
}
@@ -0,0 +1,275 @@
// $Id$
/*
* WorldGuard
* Copyright (C) 2010 sk89q <http://www.sk89q.com>
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU 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 General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package com.sk89q.worldguard.bukkit;
import com.sk89q.worldedit.BlockVector;
import com.sk89q.worldedit.Vector;
import com.sk89q.worldedit.blocks.BlockID;
import com.sk89q.worldedit.blocks.BlockType;
import com.sk89q.worldedit.blocks.ItemID;
import org.bukkit.ChatColor;
import org.bukkit.Location;
import org.bukkit.Server;
import org.bukkit.World;
import org.bukkit.block.Block;
import org.bukkit.entity.*;
import org.bukkit.inventory.ItemStack;
import java.util.List;
public class BukkitUtil {
private BukkitUtil() {
}
/**
* Converts the location of a Bukkit block to a WorldEdit vector.
*
* @param block The block to convert
* @return The block's location as a BlockVector
*/
public static BlockVector toVector(Block block) {
return new BlockVector(block.getX(), block.getY(), block.getZ());
}
/**
* Converts a Bukkit location to a WorldEdit vector.
*
* @param loc A Bukkit Location
* @return A Vector with the location's x, y, and z values
*/
public static Vector toVector(Location loc) {
return new Vector(loc.getX(), loc.getY(), loc.getZ());
}
/**
* Converts a Bukkit vector to a WorldEdit vector.
*
* @param vector The Bukkit vector
* @return A WorldEdit vector with the same values as the Bukkit vector.
*/
public static Vector toVector(org.bukkit.util.Vector vector) {
return new Vector(vector.getX(), vector.getY(), vector.getZ());
}
/**
* Converts a WorldEdit vector to a Bukkit location.
*
* @param world The World to create the new Location with
* @param vec The vector to use for coordinates
* @return The Vector as a location with a World of world
*/
public static Location toLocation(World world, Vector vec) {
return new Location(world, vec.getX(), vec.getY(), vec.getZ());
}
/**
* Matches one player based on name.
*
* @param server The server to check
* @param name The name to attempt to match
* @deprecated see {@link WorldGuardPlugin#matchSinglePlayer(org.bukkit.command.CommandSender, String)}
* @return The matched player if any, otherwise null
*/
@Deprecated
public static Player matchSinglePlayer(Server server, String name) {
List<Player> players = server.matchPlayer(name);
if (players.size() == 0) {
return null;
}
return players.get(0);
}
/**
* Drops a sign item and removes a sign.
*
* @param block The block
* @deprecated see {@link org.bukkit.block.Block#breakNaturally()}
*/
@Deprecated
public static void dropSign(Block block) {
block.setTypeId(0);
block.getWorld().dropItemNaturally(block.getLocation(),
new ItemStack(ItemID.SIGN, 1));
}
/**
* Sets the given block to fluid water.
* Used by addSpongeWater()
*
* @param world
* @param ox
* @param oy
* @param oz
*/
public static void setBlockToWater(World world, int ox, int oy, int oz) {
Block block = world.getBlockAt(ox, oy, oz);
int id = block.getTypeId();
if (id == 0) {
block.setTypeId(8);
}
}
/**
* Checks if the given block is water
*
* @param world the world
* @param ox x
* @param oy y
* @param oz z
* @return true if it's water
*/
public static boolean isBlockWater(World world, int ox, int oy, int oz) {
Block block = world.getBlockAt(ox, oy, oz);
int id = block.getTypeId();
return id == 8 || id == 9;
}
/**
* Find a position for the player to stand that is not inside a block.
* Blocks above the player will be iteratively tested until there is
* a series of two free blocks. The player will be teleported to
* that free position.
*
* @param player
*/
public static void findFreePosition(Player player) {
Location loc = player.getLocation();
int x = loc.getBlockX();
int y = Math.max(0, loc.getBlockY());
int origY = y;
int z = loc.getBlockZ();
World world = player.getWorld();
byte free = 0;
while (y <= world.getMaxHeight() + 1) {
if (BlockType.canPassThrough(world.getBlockTypeIdAt(x, y, z))) {
free++;
} else {
free = 0;
}
if (free == 2) {
if (y - 1 != origY || y == 1) {
loc.setX(x + 0.5);
loc.setY(y);
loc.setZ(z + 0.5);
if (y <= 2 && world.getBlockAt(x,0,z).getTypeId() == BlockID.AIR) {
world.getBlockAt(x,0,z).setTypeId(20);
loc.setY(2);
}
player.setFallDistance(0F);
player.teleport(loc);
}
return;
}
y++;
}
}
/**
* Replace color macros in a string. The macros are in the form of `[char]
* where char represents the color. R is for red, Y is for yellow,
* G is for green, C is for cyan, B is for blue, and P is for purple.
* The uppercase versions of those are the darker shades, while the
* lowercase versions are the lighter shades. For white, it's 'w', and
* 0-2 are black, dark grey, and grey, respectively.
*
* @param str
* @return color-coded string
*/
public static String replaceColorMacros(String str) {
str = str.replace("&r", ChatColor.RED.toString());
str = str.replace("&R", ChatColor.DARK_RED.toString());
str = str.replace("&y", ChatColor.YELLOW.toString());
str = str.replace("&Y", ChatColor.GOLD.toString());
str = str.replace("&g", ChatColor.GREEN.toString());
str = str.replace("&G", ChatColor.DARK_GREEN.toString());
str = str.replace("&c", ChatColor.AQUA.toString());
str = str.replace("&C", ChatColor.DARK_AQUA.toString());
str = str.replace("&b", ChatColor.BLUE.toString());
str = str.replace("&B", ChatColor.DARK_BLUE.toString());
str = str.replace("&p", ChatColor.LIGHT_PURPLE.toString());
str = str.replace("&P", ChatColor.DARK_PURPLE.toString());
str = str.replace("&0", ChatColor.BLACK.toString());
str = str.replace("&1", ChatColor.DARK_GRAY.toString());
str = str.replace("&2", ChatColor.GRAY.toString());
str = str.replace("&w", ChatColor.WHITE.toString());
return str;
}
/**
* Returns whether our running CraftBukkit already supports
* the HangingEvent instead of the PaintingEvent
*
* @return true if the hanging event is supported
*/
public static boolean hasHangingEvent() {
Class<?> tmp = null;
try {
tmp = Class.forName("org.bukkit.event.hanging.HangingEvent");
} catch (ClassNotFoundException ignored) { }
return (tmp != null);
}
/**
* Search an enum for a value, and return the first one found. Return null if the
* enum entry is not found.
*
* @param enumType enum class
* @param values values to test
* @return a value in the enum or null
*/
public static <T extends Enum<T>> T tryEnum(Class<T> enumType, String ... values) {
for (String val : values) {
try {
return Enum.valueOf(enumType, val);
} catch (IllegalArgumentException e) {
}
}
return null;
}
static void checkAndDestroy(World world, int x, int y, int z, int required) {
if (world.getBlockTypeIdAt(x, y, z) == required) {
world.getBlockAt(x, y, z).setTypeId(BlockID.AIR);
}
}
static void checkAndDestroyAround(World world, int x, int y, int z, int required) {
checkAndDestroy(world, x, y, z + 1, required);
checkAndDestroy(world, x, y, z - 1, required);
checkAndDestroy(world, x, y + 1, z, required);
checkAndDestroy(world, x, y - 1, z, required);
checkAndDestroy(world, x + 1, y, z, required);
checkAndDestroy(world, x - 1, y, z, required);
}
}
@@ -0,0 +1,413 @@
// $Id$
/*
* WorldGuard
* Copyright (C) 2010 sk89q <http://www.sk89q.com>
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU 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 General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package com.sk89q.worldguard.bukkit;
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.Level;
import java.util.logging.Logger;
import org.bukkit.World;
import org.bukkit.entity.Player;
import org.yaml.snakeyaml.DumperOptions.FlowStyle;
import com.sk89q.commandbook.CommandBook;
import com.sk89q.commandbook.GodComponent;
import com.sk89q.rebar.config.ConfigurationException;
import com.sk89q.rebar.config.PairedKeyValueLoaderBuilder;
import com.sk89q.rebar.config.YamlConfigurationFile;
import com.sk89q.rebar.config.YamlStyle;
import com.sk89q.rebar.config.types.LowercaseStringLoaderBuilder;
import com.sk89q.rebar.config.types.StringLoaderBuilder;
import com.sk89q.rebar.util.LoggerUtils;
import com.sk89q.rulelists.RuleEntryLoader;
import com.sk89q.worldguard.LocalPlayer;
import com.sk89q.worldguard.blacklist.Blacklist;
/**
* Represents the global configuration and also delegates configuration
* for individual worlds.
*/
public class ConfigurationManager {
private static Logger logger = LoggerUtils.getLogger(RuleEntryLoader.class, "[WorldGuard] ");
private static final String DEFAULT_RULELIST_PATH = "rulelist.yml";
private static final String DEFAULT_BLACKLIST_PATH = "worlds/%world%/blacklist.txt";
private static final String DEFAULT_WORLD_CONFIG_PATH = "worlds/%world%/config.yml";
static final YamlStyle YAML_STYLE = new YamlStyle(FlowStyle.BLOCK);
private WorldGuardPlugin plugin;
private ConcurrentMap<String, WorldConfiguration> worlds;
private YamlConfigurationFile config;
private Map<String, String> ruleLists = new HashMap<String, String>();
private Map<String, String> blacklists = new HashMap<String, String>();
private Map<String, String> worldConfigs = new HashMap<String, String>();
@Deprecated
private Set<String> hasGodMode = new HashSet<String>();
private Set<String> hasAmphibious = new HashSet<String>();
private boolean hasCommandBookGodMode = false;
/* Configuration data start */
public boolean useRegionsScheduler;
public boolean useRegionsCreatureSpawnEvent;
public boolean usePlayerMove;
public Map<String, String> hostKeys = new HashMap<String, String>();
public boolean useSqlDatabase = false;
public String sqlDsn;
public String sqlUsername;
public String sqlPassword;
/* Configuration data end */
/**
* Construct the object.
*
* @param plugin the plugin instance
*/
public ConfigurationManager(WorldGuardPlugin plugin) {
this.plugin = plugin;
this.worlds = new ConcurrentHashMap<String, WorldConfiguration>();
}
/**
* Load the configuration.
*/
public void load() {
loadConfig();
// Regions settings
useRegionsScheduler = config.getBoolean("regions.use-scheduler", true);
useRegionsCreatureSpawnEvent = config.getBoolean("regions.use-creature-spawn-event", true);
// Regions SQL settings
useSqlDatabase = config.getBoolean("regions.sql.use", false);
sqlDsn = config.getString("regions.sql.dsn", "jdbc:mysql://localhost/worldguard");
sqlUsername = config.getString("regions.sql.username", "worldguard");
sqlPassword = config.getString("regions.sql.password", "worldguard");
// Other settings
usePlayerMove = config.getBoolean("use-player-move-event", true);
// Load host keys
hostKeys = config.mapOf("host-keys",
PairedKeyValueLoaderBuilder.build(
new LowercaseStringLoaderBuilder(), new StringLoaderBuilder()));
// Load rule list filenames
if (config.contains("rulelists")) {
ruleLists = config.mapOf("rulelists",
PairedKeyValueLoaderBuilder.build(
new LowercaseStringLoaderBuilder(), new StringLoaderBuilder()));
} else {
config.setNode("rulelists").set("__default__", DEFAULT_RULELIST_PATH);
ruleLists = new HashMap<String, String>();
ruleLists.put("__default__", DEFAULT_RULELIST_PATH);
}
// Load blacklist filenames
if (config.contains("blacklists")) {
blacklists = config.mapOf("blacklists",
PairedKeyValueLoaderBuilder.build(
new LowercaseStringLoaderBuilder(), new StringLoaderBuilder()));
} else {
config.setNode("blacklists").set("__default__", DEFAULT_BLACKLIST_PATH);
blacklists = new HashMap<String, String>();
blacklists.put("__default__", DEFAULT_BLACKLIST_PATH);
}
// Load world config filenames
if (config.contains("world-configs")) {
worldConfigs = config.mapOf("world-configs",
PairedKeyValueLoaderBuilder.build(
new LowercaseStringLoaderBuilder(), new StringLoaderBuilder()));
} else {
config.setNode("world-configs").set("__default__", DEFAULT_WORLD_CONFIG_PATH);
worldConfigs = new HashMap<String, String>();
worldConfigs.put("__default__", DEFAULT_WORLD_CONFIG_PATH);
}
// Load configurations for each world
for (World world : plugin.getServer().getWorlds()) {
get(world);
}
saveConfig();
}
/**
* Unload the configuration.
*/
public void unload() {
worlds.clear();
}
/**
* Load the configuration from file.
*/
private void loadConfig() {
config = new YamlConfigurationFile(new File(plugin.getDataFolder(), "config.yml"), YAML_STYLE);
try {
config.load();
} catch (IOException e) {
logger.log(Level.SEVERE, "Error reading config.yml for global config", e);
} catch (ConfigurationException e) {
logger.log(Level.SEVERE, "Error reading config.yml for global config", e);
}
}
/**
* Save the configuration to file.
*/
private void saveConfig() {
config.setHeader(
"# GLOBAL CONFIGURATION FILE\r\n" +
"#\r\n" +
"# Everything in here applies to all worlds. For world-specific settings, edit \r\n" +
"# the files in plugins/WorldGuard/worlds/WORLD_NAME_HERE/config.yml\r\n" +
"#\r\n" +
"# The official format of this file is called YAML. If you've never had to\r\n" +
"# edit one before, you should REALLY read http://wiki.sk89q.com/wiki/Editing_YAML\r\n");
try {
config.save();
} catch (IOException e) {
logger.log(Level.SEVERE, "Failed to save configuration", e);
}
}
/**
* Get the configuration for a world.
*
* @param world The world to get the configuration for
* @return {@code world}'s configuration
*/
public WorldConfiguration get(World world) {
String worldName = world.getName();
WorldConfiguration config = worlds.get(worldName);
WorldConfiguration newConfig = null;
while (config == null) {
if (newConfig == null) {
newConfig = new WorldConfiguration(plugin, worldName, this, this.config);
}
worlds.putIfAbsent(world.getName(), newConfig);
config = worlds.get(world.getName());
}
return config;
}
/**
* Get the RuleList file for the given world.
*
* @param worldName world
* @return file (which may or may not exist)
*/
File getRuleListFile(String worldName) {
String path = ruleLists.get(worldName.toLowerCase());
if (path == null) {
path = ruleLists.get("__default__");
}
if (path == null) {
path = DEFAULT_RULELIST_PATH;
}
path = path.replace("%world%", worldName);
File file = new File(plugin.getDataFolder(), path);
if (!file.exists()) {
plugin.createDefaultConfiguration(file, "rulelist.yml");
}
return file;
}
/**
* Get the blacklist file for the given world.
*
* @param worldName world
* @return file (which may or may not exist)
*/
File getBlacklistFile(String worldName) {
String path = blacklists.get(worldName.toLowerCase());
File file;
if (path == null) {
path = blacklists.get("__default__");
}
if (path == null) {
path = DEFAULT_BLACKLIST_PATH;
}
path = path.replace("%world%", worldName);
file = new File(plugin.getDataFolder(), path);
if (!file.exists()) {
plugin.createDefaultConfiguration(file, "blacklist.txt");
}
return file;
}
/**
* Get the world configuration file for the given world.
*
* @param worldName world
* @return file (which may or may not exist)
*/
File getWorldConfigFile(String worldName) {
String path = worldConfigs.get(worldName.toLowerCase());
File file;
if (path == null) {
path = worldConfigs.get("__default__");
}
if (path == null) {
path = DEFAULT_WORLD_CONFIG_PATH;
}
path = path.replace("%world%", worldName);
file = new File(plugin.getDataFolder(), path);
return file;
}
/**
* Forget a player.
*
* @param player The player to forget about
*/
void forgetPlayer(LocalPlayer player) {
for (Map.Entry<String, WorldConfiguration> entry
: worlds.entrySet()) {
// The blacklist needs to forget players
Blacklist bl = entry.getValue().getBlacklist();
if (bl != null) {
bl.forgetPlayer(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.
*
* @param player The player to check
* @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());
}
/**
* Enable amphibious mode for a player.
*
* @param player The player to enable amphibious mode for
*/
public void enableAmphibiousMode(Player player) {
hasAmphibious.add(player.getName());
}
/**
* Disable amphibious mode for a player.
*
* @param player The player to disable amphibious mode for
*/
public void disableAmphibiousMode(Player player) {
hasAmphibious.remove(player.getName());
}
/**
* Check to see if amphibious mode is enabled for a player.
*
* @param player The player to check
* @return Whether {@code player} has amphibious mode
*/
public boolean hasAmphibiousMode(Player player) {
return hasAmphibious.contains(player.getName());
}
/**
* Check and store whether CommandBook is installed.
*/
void updateCommandBookGodMode() {
try {
if (plugin.getServer().getPluginManager().isPluginEnabled("CommandBook")) {
Class.forName("com.sk89q.commandbook.GodComponent");
hasCommandBookGodMode = true;
return;
}
} catch (ClassNotFoundException ignore) {}
hasCommandBookGodMode = false;
}
/**
* Return whether CommandBook is available for God mode usage.
*
* @return true if it available
*/
boolean hasCommandBookGodMode() {
return hasCommandBookGodMode;
}
}
@@ -1,81 +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.protection.events;
import org.bukkit.entity.Player;
import org.bukkit.event.Cancellable;
import org.bukkit.event.Event;
import org.bukkit.event.HandlerList;
/**
* This event is fired when PVP is disallowed between players due to a "pvp deny" flag.
* Cancelling this event allows the PVP in spite of this.
*
* @author Score_Under
*/
public class DisallowedPVPEvent extends Event implements Cancellable {
private static final HandlerList handlers = new HandlerList();
private boolean cancelled = false;
private final Player attacker;
private final Player defender;
private final Event event;
public DisallowedPVPEvent(final Player attacker, final Player defender, Event event) {
this.attacker = attacker;
this.defender = defender;
this.event = event;
}
public boolean isCancelled() {
return cancelled;
}
public void setCancelled(boolean cancelled) {
this.cancelled = cancelled;
}
/**
* @return the attacking player.
*/
public Player getAttacker() {
return attacker;
}
/**
* @return the defending player.
*/
public Player getDefender() {
return defender;
}
public Event getCause() {
return event;
}
@Override
public HandlerList getHandlers() {
return handlers;
}
public static HandlerList getHandlerList() {
return handlers;
}
}
// $Id$
/*
* WorldGuard
* Copyright (C) 2010 sk89q <http://www.sk89q.com>
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU 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 General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package com.sk89q.worldguard.bukkit;
import org.bukkit.entity.Player;
import org.bukkit.event.Cancellable;
import org.bukkit.event.Event;
import org.bukkit.event.HandlerList;
import org.bukkit.event.entity.EntityDamageByEntityEvent;
/**
* This event is fired when PVP is disallowed between players due to a "pvp deny" flag.
* Cancelling this event allows the PVP in spite of this.
*
* @author Score_Under
*/
public class DisallowedPVPEvent extends Event implements Cancellable {
private static final HandlerList handlers = new HandlerList();
private boolean cancelled = false;
private final Player attacker;
private final Player defender;
private final EntityDamageByEntityEvent event;
public DisallowedPVPEvent(final Player attacker, final Player defender, EntityDamageByEntityEvent event) {
this.attacker = attacker;
this.defender = defender;
this.event = event;
}
public boolean isCancelled() {
return cancelled;
}
public void setCancelled(boolean cancelled) {
this.cancelled = cancelled;
}
/**
* @return the attacking player.
*/
public Player getAttacker() {
return attacker;
}
/**
* @return the defending player.
*/
public Player getDefender() {
return defender;
}
public EntityDamageByEntityEvent getCause() {
return event;
}
@Override
public HandlerList getHandlers() {
return handlers;
}
public static HandlerList getHandlerList() {
return handlers;
}
}
@@ -0,0 +1,305 @@
// $Id$
/*
* This file is a part of WorldGuard.
* Copyright (c) sk89q <http://www.sk89q.com>
* Copyright (c) the 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
* (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
* GNU 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 java.util.logging.Logger;
import org.bukkit.ChatColor;
import org.bukkit.Chunk;
import org.bukkit.Server;
import org.bukkit.World;
import org.bukkit.entity.Animals;
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.event.EventHandler;
import org.bukkit.event.EventPriority;
import org.bukkit.event.Listener;
import org.bukkit.event.block.BlockBurnEvent;
import org.bukkit.event.block.BlockFormEvent;
import org.bukkit.event.block.BlockFromToEvent;
import org.bukkit.event.block.BlockIgniteEvent;
import org.bukkit.event.block.BlockPhysicsEvent;
import org.bukkit.event.block.BlockSpreadEvent;
import org.bukkit.event.block.LeavesDecayEvent;
import org.bukkit.event.entity.CreatureSpawnEvent;
import org.bukkit.event.entity.EntityExplodeEvent;
import org.bukkit.event.entity.ExplosionPrimeEvent;
import org.bukkit.event.player.PlayerJoinEvent;
import org.bukkit.event.world.ChunkLoadEvent;
import org.bukkit.plugin.PluginManager;
import com.sk89q.rebar.util.LoggerUtils;
/**
* Handles the "stop lag" mode.
*/
public class LagStopMode implements Listener {
private static final Logger logger = LoggerUtils.getLogger(LagStopMode.class,
"[WorldGuard] Lag Stop Mode: ");
private final WorldGuardPlugin plugin;
private boolean enabled = false;
private boolean removeAnimals = true;
LagStopMode(WorldGuardPlugin plugin) {
this.plugin = plugin;
}
/**
* Register this class's events.
*/
void registerEvents() {
PluginManager pm = plugin.getServer().getPluginManager();
pm.registerEvents(this, plugin);
}
/**
* Get whether the lag stop mode is enabled.
*
* @return true if it's enabled
*/
public boolean isEnabled() {
return enabled;
}
/**
* Enable the lag stop mode. This will start the process and emit messages.
*
* @param unloadChunks true to unload chunks
*/
public void enable(boolean unloadChunks) {
if (!enabled) {
Server server = plugin.getServer();
server.broadcastMessage(ChatColor.GRAY
+ "(WorldGuard's 'lag stop' mode has been enabled. Some parts of the game may be 'frozen'. Keep calm and carry on.)");
// Remove entities
server.broadcastMessage(ChatColor.GRAY + "(Please wait... removing entities...)");
for (World world : server.getWorlds()) {
freeUp(world);
}
// Unloading chunks
if (unloadChunks) {
server.broadcastMessage(ChatColor.GRAY + "(Please wait... garbage collecting chunks...)");
for (World world : server.getWorlds()) {
Chunk[] chunks = world.getLoadedChunks();
for (Chunk chunk : chunks) {
chunk.unload(true, true);
}
}
}
server.broadcastMessage(ChatColor.GRAY + "(Completed. Lag stop mode is still enabled.)");
}
this.enabled = true;
}
/**
* Disable the lag stop mode.
*/
public void disable() {
if (enabled) {
Server server = plugin.getServer();
server.broadcastMessage(ChatColor.GRAY
+ "(WorldGuard's 'lag stop' mode is now off. Everything should proceed to start working again.)");
}
this.enabled = false;
}
/**
* Returns whether animals are being removed.
*
* @return true if animals are being removed
*/
public boolean isRemovingAnimals() {
return removeAnimals;
}
/**
* Set whether animals should be removed.
*
* @param removeAnimals true to remove animals
*/
public void setRemoveAnimals(boolean removeAnimals) {
this.removeAnimals = removeAnimals;
}
/**
* Remove items and other things within the chunk.
*
* @param plugin the plugin
* @param chunk the chunk to halt
*/
private void freeUp(Chunk chunk) {
int removed = 0;
for (Entity entity : chunk.getEntities()) {
if (shouldRemove(entity)) {
entity.remove();
removed++;
}
}
if (removed > 50) {
logger.info(removed + " entities (>50) auto-removed from " + chunk.toString());
}
}
/**
* Remove items and other things within the world.
*
* @param plugin the plugin
* @param world the world to halt
*/
private void freeUp(World world) {
int removed = 0;
for (Entity entity : world.getEntities()) {
if (shouldRemove(entity)) {
entity.remove();
removed++;
}
}
if (removed > 50) {
logger.info(removed + " entities (>50) auto-removed from " + world.toString());
}
}
/**
* Returns whether an entity should be removed.
*
* @param entity the entity to check
* @return true if it should be removed
*/
private boolean shouldRemove(Entity entity) {
return entity instanceof Item
|| entity instanceof TNTPrimed
|| entity instanceof ExperienceOrb
|| entity instanceof FallingBlock
|| (entity instanceof LivingEntity
&& !(entity instanceof Tameable)
&& !(entity instanceof Player)
&& (removeAnimals || !(entity instanceof Animals)));
}
@EventHandler(priority = EventPriority.LOWEST)
public void onPlayerJoin(PlayerJoinEvent event) {
Player player = event.getPlayer();
World world = player.getWorld();
if (enabled) {
player.sendMessage(ChatColor.GRAY
+ "WorldGuard's 'lag stop' mode has been enabled. Some parts of the game may be 'frozen'.");
freeUp(world);
}
}
@EventHandler(priority = EventPriority.LOWEST)
public void onBlockFromTo(BlockFromToEvent event) {
if (enabled) {
event.setCancelled(true);
}
}
@EventHandler(priority = EventPriority.LOWEST)
public void onBlockIgnite(BlockIgniteEvent event) {
if (enabled) {
event.setCancelled(true);
}
}
@EventHandler(priority = EventPriority.LOWEST)
public void onBlockBurn(BlockBurnEvent event) {
if (enabled) {
event.setCancelled(true);
}
}
@EventHandler(priority = EventPriority.LOWEST)
public void onBlockPhysics(BlockPhysicsEvent event) {
if (enabled) {
event.setCancelled(true);
}
}
@EventHandler(priority = EventPriority.LOWEST)
public void onBlockForm(BlockFormEvent event) {
if (enabled) {
event.setCancelled(true);
}
}
@EventHandler(priority = EventPriority.LOWEST)
public void onLeavesDecay(LeavesDecayEvent event) {
if (enabled) {
event.setCancelled(true);
}
}
@EventHandler(priority = EventPriority.LOWEST)
public void onBlockSpread(BlockSpreadEvent event) {
if (enabled) {
event.setCancelled(true);
}
}
@EventHandler(priority = EventPriority.LOWEST)
public void onEntityExplode(EntityExplodeEvent event) {
if (enabled) {
event.setCancelled(true);
}
}
@EventHandler(priority = EventPriority.LOWEST)
public void onExplosionPrime(ExplosionPrimeEvent event) {
if (enabled) {
event.setCancelled(true);
}
}
@EventHandler(priority = EventPriority.LOWEST)
public void onCreatureSpawn(CreatureSpawnEvent event) {
if (enabled) {
event.setCancelled(true);
}
}
@EventHandler(priority = EventPriority.LOWEST)
public void onChunkLoad(ChunkLoadEvent event) {
if (enabled) {
freeUp(event.getChunk());
}
}
}
@@ -0,0 +1,74 @@
// $Id$
/*
* WorldGuard
* Copyright (C) 2010 sk89q <http://www.sk89q.com>
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU 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 General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package com.sk89q.worldguard.bukkit;
import java.util.logging.Handler;
import java.util.logging.Level;
import java.util.logging.LogRecord;
import org.bukkit.ChatColor;
import org.bukkit.command.CommandSender;
/**
* Sends all logger messages to a player.
*/
public class LoggerToChatHandler extends Handler {
/**
* Player.
*/
private CommandSender player;
/**
* Construct the object.
*
* @param player
*/
public LoggerToChatHandler(CommandSender player) {
this.player = player;
}
/**
* Close the handler.
*/
@Override
public void close() {
}
/**
* Flush the output.
*/
@Override
public void flush() {
}
/**
* Publish a log record.
*/
@Override
public void publish(LogRecord record) {
if (record.getLevel().intValue() >= Level.WARNING.intValue()) {
player.sendMessage(ChatColor.RED + record.getLevel().getName() + ": "
+ ChatColor.YELLOW + record.getMessage());
} else {
player.sendMessage(ChatColor.GRAY + record.getLevel().getName() + ": "
+ ChatColor.WHITE + record.getMessage());
}
}
}
@@ -0,0 +1,96 @@
// $Id$
/*
* This file is a part of WorldGuard.
* Copyright (c) sk89q <http://www.sk89q.com>
* Copyright (c) the 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
* (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
* GNU 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 org.bukkit.Location;
import org.bukkit.World;
import org.bukkit.block.Block;
import org.bukkit.entity.Entity;
import com.sk89q.worldedit.Vector;
import com.sk89q.worldguard.region.ApplicableRegionSet;
import com.sk89q.worldguard.region.RegionManager;
import com.sk89q.worldguard.region.RegionQueryCacheEntry;
/**
* A class that will cache all region queries. Instances of this class are created
* via an instance of {@link RegionQueryCache} and represent a point in time.
*/
public final class RegionQuery {
private final WorldGuardPlugin plugin;
private final RegionQueryCacheEntry entry;
/**
* Construct the instance with the underlying cache entry.
*
* @param entry
*/
RegionQuery(WorldGuardPlugin plugin, RegionQueryCacheEntry entry) {
this.plugin = plugin;
this.entry = entry;
}
/**
* Get an {@link ApplicableRegionSet} for a given location. The result may have been
* temporarily cached for the given event, or null if region protection has
* been disabled for the the world of the given location.
*
* @param location the location to check
* @return the set, or null if region protection is disabled for the given location
*/
public ApplicableRegionSet lookup(Location location) {
World world = location.getWorld();
Vector vector = BukkitUtil.toVector(location);
ConfigurationManager config = plugin.getGlobalStateManager();
WorldConfiguration worldConfig = config.get(world);
RegionManager regionManager = plugin.getGlobalRegionManager();
if (!worldConfig.useRegions) {
return null;
}
return entry.lookup(regionManager.get(world), vector);
}
/**
* Get an {@link ApplicableRegionSet} for a given block. The result may have been
* temporarily cached for the given event, or null if region protection has
* been disabled for the the world of the given block.
*
* @param block the block to check
* @return the set, or null if region protection is disabled for the given block
*/
public ApplicableRegionSet lookup(Block block) {
return lookup(block.getLocation());
}
/**
* Get an {@link ApplicableRegionSet} for a given entity. The result may have been
* temporarily cached for the given event, or null if region protection has
* been disabled for the the world of the given entity.
*
* @param entity the entity to check
* @return the set, or null if region protection is disabled for the given entity
*/
public ApplicableRegionSet lookup(Entity entity) {
return lookup(entity.getLocation());
}
}
@@ -0,0 +1,53 @@
// $Id$
/*
* This file is a part of WorldGuard.
* Copyright (c) sk89q <http://www.sk89q.com>
* Copyright (c) the 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
* (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
* GNU 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 org.bukkit.event.Event;
import com.sk89q.worldguard.region.AbstractRegionQueryCache;
/**
* An implementation of {@link AbstractRegionQueryCache} for Bukkit. This implementation
* is thread-safe.
*/
public final class RegionQueryCache extends AbstractRegionQueryCache {
private final WorldGuardPlugin plugin;
/**
* Construct the cache with the given plugin instance.
*
* @param plugin plugin instance
*/
public RegionQueryCache(WorldGuardPlugin plugin) {
this.plugin = plugin;
}
/**
* Get a {@link RegionQuery} object that can cache region queries. The object
* returned by this method does not need to be cached. It is merely a proxy class.
*
* @param event the event to cache against
* @return an object to perform lookups against
*/
public RegionQuery against(Event event) {
return new RegionQuery(plugin, get(event));
}
}
@@ -0,0 +1,332 @@
// $Id$
/*
* WorldGuard
* Copyright (C) 2010 sk89q <http://www.sk89q.com>
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU 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 General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package com.sk89q.worldguard.bukkit;
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 org.bukkit.Server;
import org.bukkit.World;
import org.bukkit.entity.Entity;
import org.bukkit.plugin.Plugin;
import com.sk89q.worldguard.region.RegionManager;
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 {
if (field.getName().equalsIgnoreCase("CONFIG_HEADER")) continue;
Object val = field.get(config);
configLog.put(field.getName(), 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]",
entry.getValue(),
(float) (entry.getValue() / (double) loadedChunkCount));
}
i++;
}
append(log);
appendln();
}
private void appendWorldConfigurations(WorldGuardPlugin plugin, List<World> worlds,
RegionManager 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());
}
/*RegionIndex worldRegions = regionMgr.get(world);
regionsLog.put("Type", worldRegions.getClass().getCanonicalName());
regionsLog.put("Number of regions", worldRegions.getRegions().size());
LogListBlock globalRegionLog = regionsLog.putChild("Global region");
Region globalRegion = worldRegions.getRegion("__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();
}
}
@@ -0,0 +1,196 @@
// $Id$
/*
* WorldGuard
* Copyright (C) 2010 sk89q <http://www.sk89q.com>
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU 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 General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package com.sk89q.worldguard.bukkit;
import org.bukkit.Material;
import org.bukkit.World;
import org.bukkit.block.Block;
import com.sk89q.worldedit.blocks.BlockID;
/**
* An applicator of the sponge feature.
*/
class SpongeApplicator {
private final int spongeRadius;
private final boolean useRedstone;
private final boolean refillArea;
/**
* Construct a new applicator.
*
* @param spongeRadius the radius of the sponge's effect
* @param useRedstone use Redstone
* @param refillArea refill the area if a sponge is removed
*/
public SpongeApplicator(int spongeRadius, boolean useRedstone, boolean refillArea) {
this.spongeRadius = spongeRadius;
this.useRedstone = useRedstone;
this.refillArea = refillArea;
}
/**
* Returns whether the block at the given position is water.
*
* @param world world
* @param x x
* @param y y
* @param z z
* @return true if it's water
*/
private static boolean isWater(World world, int x, int y, int z) {
int type = world.getBlockTypeIdAt(x, y, z);
return type == BlockID.WATER || type == BlockID.STATIONARY_WATER;
}
/**
* Returns whether the given sponge is an active sponge.
*
* @param block block to check
* @return true if it's active
*/
public boolean isActiveSponge(Block block) {
return block.getType() == Material.SPONGE
&& (!useRedstone || !block.isBlockIndirectlyPowered());
}
/**
* Return true if a given block near an active sponge.
*
* @param blockTo location of the block
* @return true if it's near a sponge (and water should be cancelled)
*/
public boolean isNearSponge(Block blockTo) {
World world = blockTo.getWorld();
int ox = blockTo.getX();
int oy = blockTo.getY();
int oz = blockTo.getZ();
for (int cx = -spongeRadius; cx <= spongeRadius; cx++) {
for (int cy = -spongeRadius; cy <= spongeRadius; cy++) {
for (int cz = -spongeRadius; cz <= spongeRadius; cz++) {
Block sponge = world.getBlockAt(ox + cx, oy + cy, oz + cz);
if (isActiveSponge(sponge)) {
return true;
}
}
}
}
return false;
}
/**
* Remove water due to a sponge from the given position.
*
* @param block the block
*/
public void clearWater(Block block) {
World world = block.getWorld();
int ox = block.getX();
int oy = block.getY();
int oz = block.getZ();
for (int cx = -spongeRadius; cx <= spongeRadius; cx++) {
for (int cy = -spongeRadius; cy <= spongeRadius; cy++) {
for (int cz = -spongeRadius; cz <= spongeRadius; cz++) {
if (isWater(world, ox + cx, oy + cy, oz + cz)) {
world.getBlockAt(ox + cx, oy + cy, oz + cz).setTypeId(0);
}
}
}
}
}
/**
* Add water due to a sponge from the given position.
*
* @param block the block
*/
public void placeWater(Block block) {
if (!refillArea) return;
World world = block.getWorld();
int ox = block.getX();
int oy = block.getY();
int oz = block.getZ();
// The negative x edge
int cx = ox - spongeRadius - 1;
for (int cy = oy - spongeRadius - 1; cy <= oy + spongeRadius + 1; cy++) {
for (int cz = oz - spongeRadius - 1; cz <= oz + spongeRadius + 1; cz++) {
if (isWater(world, cx, cy, cz)) {
world.getBlockAt(cx + 1, cy, cz).setType(Material.STATIONARY_WATER);
}
}
}
// The positive x edge
cx = ox + spongeRadius + 1;
for (int cy = oy - spongeRadius - 1; cy <= oy + spongeRadius + 1; cy++) {
for (int cz = oz - spongeRadius - 1; cz <= oz + spongeRadius + 1; cz++) {
if (isWater(world, cx, cy, cz)) {
world.getBlockAt(cx - 1, cy, cz).setType(Material.STATIONARY_WATER);
}
}
}
// The negative y edge
int cy = oy - spongeRadius - 1;
for (cx = ox - spongeRadius - 1; cx <= ox + spongeRadius + 1; cx++) {
for (int cz = oz - spongeRadius - 1; cz <= oz + spongeRadius + 1; cz++) {
if (isWater(world, cx, cy, cz)) {
world.getBlockAt(cx, cy + 1, cz).setType(Material.STATIONARY_WATER);
}
}
}
// The positive y edge
cy = oy + spongeRadius + 1;
for (cx = ox - spongeRadius - 1; cx <= ox + spongeRadius + 1; cx++) {
for (int cz = oz - spongeRadius - 1; cz <= oz + spongeRadius + 1; cz++) {
if (isWater(world, cx, cy, cz)) {
world.getBlockAt(cx, cy - 1, cz).setType(Material.STATIONARY_WATER);
}
}
}
// The negative z edge
int cz = oz - spongeRadius - 1;
for (cx = ox - spongeRadius - 1; cx <= ox + spongeRadius + 1; cx++) {
for (cy = oy - spongeRadius - 1; cy <= oy + spongeRadius + 1; cy++) {
if (isWater(world, cx, cy, cz)) {
world.getBlockAt(cx, cy, cz + 1).setType(Material.STATIONARY_WATER);
}
}
}
// The positive z edge
cz = oz + spongeRadius + 1;
for (cx = ox - spongeRadius - 1; cx <= ox + spongeRadius + 1; cx++) {
for (cy = oy - spongeRadius - 1; cy <= oy + spongeRadius + 1; cy++) {
if (isWater(world, cx, cy, cz)) {
world.getBlockAt(cx, cy, cz - 1).setType(Material.STATIONARY_WATER);
}
}
}
}
}
@@ -0,0 +1,434 @@
// $Id$
/*
* WorldGuard
* Copyright (C) 2010 sk89q <http://www.sk89q.com>
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU 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 General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package com.sk89q.worldguard.bukkit;
import java.io.File;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Collection;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.logging.Level;
import java.util.logging.Logger;
import org.bukkit.entity.Player;
import com.sk89q.rebar.config.ConfigurationException;
import com.sk89q.rebar.config.ConfigurationNode;
import com.sk89q.rebar.config.YamlConfiguration;
import com.sk89q.rebar.config.YamlConfigurationFile;
import com.sk89q.rebar.config.YamlConfigurationResource;
import com.sk89q.rebar.config.YamlStyle;
import com.sk89q.rebar.util.LoggerUtils;
import com.sk89q.rulelists.RuleList;
import com.sk89q.rulelists.RuleEntry;
import com.sk89q.rulelists.RuleEntryLoader;
import com.sk89q.rulelists.RuleTemplateEntryLoader;
import com.sk89q.worldguard.blacklist.Blacklist;
import com.sk89q.worldguard.blacklist.BlacklistLogger;
import com.sk89q.worldguard.blacklist.loggers.ConsoleLoggerHandler;
import com.sk89q.worldguard.blacklist.loggers.DatabaseLoggerHandler;
import com.sk89q.worldguard.blacklist.loggers.FileLoggerHandler;
/**
* Holds the configuration for individual worlds.
*/
public class WorldConfiguration {
private static Logger logger = LoggerUtils.getLogger(WorldConfiguration.class, "[WorldGuard] ");
private final WorldGuardPlugin plugin;
private final ConfigurationManager configMan;
private final YamlConfigurationFile config;
private final String worldName;
private Blacklist blacklist;
private RuleList ruleList = new RuleList();
private SpongeApplicator spongeApplicator = null;
/* Configuration data start */
public boolean opPermissions;
public boolean useRegions;
public boolean highFreqFlags;
public int regionWand;
public boolean regionInvinciblityRemovesMobs;
// public boolean useiConomy;
// public boolean buyOnClaim;
// public double buyOnClaimPrice;
public int maxClaimVolume;
public boolean claimOnlyInsideExistingRegions;
public int maxRegionCountPerPlayer;
public boolean signChestProtection;
public boolean disableSignChestProtectionCheck;
private Map<String, Integer> maxRegionCounts;
public boolean fireSpreadDisableToggle;
/* Configuration data end */
/**
* Construct the object.
*
* @param plugin the plugin instance
* @param worldName name of the world that this object is for
* @param configMan configuration manager
* @param parentConfig parent configuration
*/
public WorldConfiguration(WorldGuardPlugin plugin, String worldName,
ConfigurationManager configMan, ConfigurationNode parentConfig) {
this.plugin = plugin;
this.worldName = worldName;
this.configMan = configMan;
File file = configMan.getWorldConfigFile(worldName);
config = new YamlConfigurationFile(file, ConfigurationManager.YAML_STYLE);
config.setParent(parentConfig);
load();
}
/**
* Load the configuration.
*/
private void load() {
logger.info("Loading configuration for '" + worldName + "'...");
loadConfig();
// Load rule lists
ruleList.clear();
loadBuiltInRules();
loadUserRules();
loadBlacklist();
loadSettings();
saveConfig();
}
/**
* Load the configuration from file.
*/
private void loadConfig() {
try {
config.load();
} catch (IOException e) {
logger.log(Level.SEVERE, "Error reading configuration for world " + worldName, e);
} catch (ConfigurationException e) {
logger.log(Level.SEVERE, "Error reading configuration for world " + worldName, e);
}
}
/**
* Save the configuration to file.
*/
private void saveConfig() {
config.setHeader(
"# CONFIGURATION FILE FOR ONLY THIS WORLD\r\n" +
"#\r\n" +
"# Everything in here applies to ONLY this world. For global settings, edit \r\n" +
"# the file in plugins/WorldGuard/config.yml\r\n" +
"#\r\n" +
"# How do you use this file? Copy potions of the global configuration file into this file.\r\n" +
"#\r\n" +
"# EXAMPLE (remove the # in front):\r\n" +
"#physics:\r\n" +
"# block-tnt-damage: false");
try {
config.save();
} catch (IOException e) {
logger.log(Level.SEVERE, "Failed to save configuration", e);
}
}
/**
* Load the built-in rules.
*/
private void loadBuiltInRules() {
try {
RuleTemplateEntryLoader loader = new RuleTemplateEntryLoader(
plugin.getRulesListManager(), config);
for (List<RuleEntry> entries : plugin.getBuiltInRules().listOf("", loader)) {
for (RuleEntry entry : entries) {
ruleList.learn(entry);
}
}
} catch (IOException e) {
logger.log(Level.SEVERE, "Failed to load the built-in rules", e);
} catch (ConfigurationException e) {
logger.log(Level.SEVERE, "Failed to load the built-in rules", e);
}
}
/**
* Load the user rules.
*/
private void loadUserRules() {
File rulesFile = configMan.getRuleListFile(worldName);
RuleEntryLoader entryLoader = new RuleEntryLoader(plugin.getRulesListManager());
YamlConfigurationFile rulesConfig = new YamlConfigurationFile(rulesFile,
ConfigurationManager.YAML_STYLE, false);
try {
rulesConfig.load();
for (RuleEntry entry : rulesConfig.listOf(ConfigurationNode.ROOT, entryLoader)) {
ruleList.learn(entry);
}
} catch (IOException e) {
logger.log(Level.SEVERE, "Failed to load " + rulesFile.getAbsolutePath(), e);
} catch (ConfigurationException e) {
logger.log(Level.SEVERE, "Failed to load " + rulesFile.getAbsolutePath(), e);
}
}
/**
* Load the blacklist.
*/
private void loadBlacklist() {
try {
if (blacklist != null) {
blacklist.getLogger().close();
}
File blacklistFile = configMan.getBlacklistFile(worldName);
// Load blacklist settings
boolean useBlacklistAsWhitelist = config.getBoolean("blacklist.use-as-whitelist", false);
boolean logConsole = config.getBoolean("blacklist.logging.console.enable", true);
boolean logDatabase = config.getBoolean("blacklist.logging.database.enable", false);
String dsn = config.getString("blacklist.logging.database.dsn", "jdbc:mysql://localhost:3306/minecraft");
String user = config.getString("blacklist.logging.database.user", "root");
String pass = config.getString("blacklist.logging.database.pass", "");
String table = config.getString("blacklist.logging.database.table", "blacklist_events");
boolean logFile = config.getBoolean("blacklist.logging.file.enable", false);
String logFilePattern = config.getString("blacklist.logging.file.path", "worldguard/logs/%Y-%m-%d.log");
int logFileCacheSize = Math.max(1, config.getInt("blacklist.logging.file.open-files", 10));
Blacklist newBlacklist = new BukkitBlacklist(useBlacklistAsWhitelist, plugin);
newBlacklist.load(blacklistFile);
// If the blacklist is empty, then set the field to null and save some resources
if (newBlacklist.isEmpty()) {
this.blacklist = null;
} else {
this.blacklist = newBlacklist;
logger.log(Level.INFO, "Blacklist loaded.");
BlacklistLogger blacklistLogger = newBlacklist.getLogger();
if (logDatabase)
blacklistLogger.addHandler(new DatabaseLoggerHandler(dsn, user,
pass, table, worldName, logger));
if (logConsole)
blacklistLogger.addHandler(new ConsoleLoggerHandler(worldName,
logger));
if (logFile) {
FileLoggerHandler handler = new FileLoggerHandler(logFilePattern,
logFileCacheSize, worldName, logger);
blacklistLogger.addHandler(handler);
}
}
} catch (FileNotFoundException e) {
logger.log(Level.WARNING, "WorldGuard blacklist does not exist", e);
} catch (IOException e) {
logger.log(Level.WARNING, "Could not load blacklist", e);
}
}
/**
* Load the settings.
*/
private void loadSettings() {
opPermissions = config.getBoolean("op-permissions", true);
boolean simulateSponge = config.getBoolean("simulation.sponge.enable", true);
int spongeRadius = Math.max(1, config.getInt("simulation.sponge.radius", 3)) - 1;
boolean redstoneSponges = config.getBoolean("simulation.sponge.redstone", false);
boolean refillArea = config.getBoolean("simulation.sponge.refill-area", false);
if (simulateSponge) {
spongeApplicator = new SpongeApplicator(spongeRadius, redstoneSponges, refillArea);
}
signChestProtection = config.getBoolean("chest-protection.enable", false);
disableSignChestProtectionCheck = config.getBoolean("chest-protection.disable-off-check", false);
useRegions = config.getBoolean("regions.enable", true);
regionInvinciblityRemovesMobs = config.getBoolean("regions.invincibility-removes-mobs", false);
highFreqFlags = config.getBoolean("regions.high-frequency-flags", false);
regionWand = config.getInt("regions.wand", 287);
maxClaimVolume = config.getInt("regions.max-claim-volume", 30000);
claimOnlyInsideExistingRegions = config.getBoolean("regions.claim-only-inside-existing-regions", false);
maxRegionCountPerPlayer = config.getInt("regions.max-region-count-per-player.default", 7);
maxRegionCounts = new HashMap<String, Integer>();
maxRegionCounts.put(null, maxRegionCountPerPlayer);
for (String key : config.getKeys("regions.max-region-count-per-player")) {
if (!key.equalsIgnoreCase("default")) {
Object val = config.get("regions.max-region-count-per-player." + key);
if (val != null && val instanceof Number) {
maxRegionCounts.put(key, ((Number) val).intValue());
}
}
}
// Very important part for protection!
if (useRegions) {
loadRegionModels();
}
// useiConomy = getBoolean("iconomy.enable", false);
// buyOnClaim = getBoolean("iconomy.buy-on-claim", false);
// buyOnClaimPrice = getDouble("iconomy.buy-on-claim-price", 1.0);
}
/**
* Load region protection model.
*/
private void loadRegionModels() {
List<String> filenames;
RuleEntryLoader entryLoader = new RuleEntryLoader(plugin.getRulesListManager());
// Make a default protection model list
List<String> defaultProtectionModels = new ArrayList<String>();
defaultProtectionModels.add("minimal");
// Load protection model
filenames = config.getStringList("regions.protection-models", defaultProtectionModels);
for (YamlConfiguration config : readFiles(filenames, "/models/protection/",
new File(plugin.getDataFolder(), "models/protection"))) {
for (RuleEntry entry : config.listOf(ConfigurationNode.ROOT, entryLoader)) {
ruleList.learn(entry);
}
}
}
/**
* Get the blacklist.
*
* @return the blacklist
*/
Blacklist getBlacklist() {
return blacklist;
}
/**
* Get the RuleList.
*
* @return the rule list
*/
RuleList getRuleList() {
return ruleList;
}
/**
* Get the sponge applicator.
*
* @return sponge applicator
*/
SpongeApplicator getSpongeApplicator() {
return spongeApplicator;
}
/**
* Get the world name of this configuration.
*
* @return the world name
*/
public String getWorldName() {
return this.worldName;
}
/**
* Get the maximum region count for a given player.
*
* @param player player
* @return number of regions
*/
public int getMaxRegionCount(Player player) {
int max = -1;
for (String group : plugin.getGroups(player)) {
if (maxRegionCounts.containsKey(group)) {
int groupMax = maxRegionCounts.get(group);
if (max < groupMax) max = groupMax;
}
}
if (max <= -1) {
max = maxRegionCountPerPlayer;
}
return max;
}
/**
* Read a list of files, either from the .jar (preferred) or from disk.
*
* @param filenames list of filenames
* @param internalDir the base path for the JAR files
* @param externalDir the base dir for the disk files
* @return a list of {@link YamlConfiguration}s
*/
private static List<YamlConfiguration> readFiles(Collection<String> filenames,
String internalDir, File externalDir) {
List<YamlConfiguration> configs = new ArrayList<YamlConfiguration>();
for (String filename : filenames) {
YamlConfiguration config;
// External file path
File file = new File(externalDir, filename);
file.getParentFile().mkdirs();
// Try loading from the .jar first
String path = internalDir + filename + ".yml";
config = new YamlConfigurationResource(WorldGuardPlugin.class, path);
try {
config.load();
configs.add(config);
continue; // Found!
} catch (FileNotFoundException e) {
// Do nothing
} catch (IOException e) {
logger.log(Level.SEVERE, "Failed to internal path " + path, e);
} catch (ConfigurationException e) {
logger.log(Level.SEVERE, "Failed to internal path " + path, e);
}
// Try loading from disk
config = new YamlConfigurationFile(file, new YamlStyle(), false);
try {
config.load();
configs.add(config);
continue; // Found!
} catch (FileNotFoundException e) {
logger.log(Level.SEVERE, "Failed to load " + file.getAbsolutePath());
} catch (IOException e) {
logger.log(Level.SEVERE, "Failed to load " + file.getAbsolutePath(), e);
} catch (ConfigurationException e) {
logger.log(Level.SEVERE, "Failed to load " + file.getAbsolutePath(), e);
}
}
return configs;
}
}
@@ -0,0 +1,463 @@
// $Id$
/*
* WorldGuard
* Copyright (C) 2010 sk89q <http://www.sk89q.com>
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU 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 General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package com.sk89q.worldguard.bukkit;
import org.bukkit.ChatColor;
import org.bukkit.Material;
import org.bukkit.World;
import org.bukkit.block.Block;
import org.bukkit.block.BlockState;
import org.bukkit.entity.Player;
import org.bukkit.event.EventHandler;
import org.bukkit.event.EventPriority;
import org.bukkit.event.Listener;
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.BlockFadeEvent;
import org.bukkit.event.block.BlockFormEvent;
import org.bukkit.event.block.BlockFromToEvent;
import org.bukkit.event.block.BlockIgniteEvent;
import org.bukkit.event.block.BlockIgniteEvent.IgniteCause;
import org.bukkit.event.block.BlockPhysicsEvent;
import org.bukkit.event.block.BlockPlaceEvent;
import org.bukkit.event.block.BlockSpreadEvent;
import org.bukkit.event.block.LeavesDecayEvent;
import org.bukkit.event.block.SignChangeEvent;
import com.sk89q.rulelists.DefaultAttachments;
import com.sk89q.rulelists.RuleSet;
import com.sk89q.worldedit.blocks.BlockID;
/**
* The listener for block events.
*/
class WorldGuardBlockListener implements Listener {
private WorldGuardPlugin plugin;
/**
* Construct the listener.
*
* @param plugin WorldGuard plugin
*/
WorldGuardBlockListener(WorldGuardPlugin plugin) {
this.plugin = plugin;
}
/**
* Register the events.
*/
void registerEvents() {
plugin.getServer().getPluginManager().registerEvents(this, plugin);
}
@EventHandler(priority = EventPriority.HIGH, ignoreCancelled = true)
public void onBlockDamage(BlockDamageEvent event) {
Player player = event.getPlayer();
Block blockDamaged = event.getBlock();
ConfigurationManager cfg = plugin.getGlobalStateManager();
WorldConfiguration wcfg = cfg.get(event.getBlock().getWorld());
// Cake are damaged and not broken when they are eaten, so we must
// handle them a bit separately
if (blockDamaged.getTypeId() == BlockID.CAKE_BLOCK) {
// RuleLists
RuleSet rules = wcfg.getRuleList().get(DefaultAttachments.BLOCK_INTERACT);
BukkitContext context = new BukkitContext(plugin, event);
context.setSourceEntity(player);
context.setTargetBlock(event.getBlock().getState());
if (rules.process(context)) {
event.setCancelled(true);
return;
}
}
}
@EventHandler(priority = EventPriority.HIGH, ignoreCancelled = true)
public void onBlockBreak(BlockBreakEvent event) {
Player player = event.getPlayer();
Block block = event.getBlock();
ConfigurationManager cfg = plugin.getGlobalStateManager();
WorldConfiguration wcfg = cfg.get(event.getBlock().getWorld());
// RuleLists
RuleSet rules = wcfg.getRuleList().get(DefaultAttachments.BLOCK_BREAK);
BukkitContext context = new BukkitContext(plugin, event);
context.setSourceEntity(player);
context.setTargetBlock(event.getBlock().getState());
if (rules.process(context)) {
event.setCancelled(true);
return;
}
/* --- No short-circuit returns below this line --- */
// Sponges
SpongeApplicator spongeAppl = wcfg.getSpongeApplicator();
if (spongeAppl != null && block.getType() == Material.SPONGE) {
if (spongeAppl.isActiveSponge(block)) {
spongeAppl.placeWater(block);
}
}
}
@EventHandler(ignoreCancelled = true)
public void onBlockFromTo(BlockFromToEvent event) {
Block blockFrom = event.getBlock();
Block blockTo = event.getToBlock();
boolean isWater = blockFrom.getTypeId() == 8 || blockFrom.getTypeId() == 9;
ConfigurationManager cfg = plugin.getGlobalStateManager();
WorldConfiguration wcfg = cfg.get(event.getBlock().getWorld());
// Sponges
SpongeApplicator spongeAppl = wcfg.getSpongeApplicator();
if (spongeAppl != null && isWater) {
if (spongeAppl.isNearSponge(blockTo)) {
event.setCancelled(true);
return;
}
}
// RuleLists
RuleSet rules = wcfg.getRuleList().get(DefaultAttachments.BLOCK_SPREAD);
BukkitContext context = new BukkitContext(plugin, event);
context.setSourceBlock(event.getBlock().getState());
context.setTargetBlock(event.getToBlock().getState());
if (rules.process(context)) {
event.setCancelled(true);
return;
}
}
@EventHandler(priority = EventPriority.HIGH, ignoreCancelled = true)
public void onBlockIgnite(BlockIgniteEvent event) {
IgniteCause cause = event.getCause();
Block block = event.getBlock();
World world = block.getWorld();
boolean isFireSpread = cause == IgniteCause.SPREAD;
ConfigurationManager cfg = plugin.getGlobalStateManager();
WorldConfiguration wcfg = cfg.get(world);
// Fire stop toggle
if (wcfg.fireSpreadDisableToggle && isFireSpread) {
event.setCancelled(true);
return;
}
// RuleLists
RuleSet rules;
BukkitContext context;
BlockState placedState;
switch (event.getCause()) {
case FLINT_AND_STEEL:
// Consider flint and steel as an item use
rules = wcfg.getRuleList().get(DefaultAttachments.ITEM_USE);
context = new BukkitContext(plugin, event);
context.setSourceEntity(event.getPlayer());
context.setTargetBlock(event.getBlock().getState());
context.setItem(event.getPlayer().getItemInHand()); // Should be flint and steel
// Make a virtual new state
placedState = event.getBlock().getState();
placedState.setType(Material.FIRE);
context.setPlacedBlock(placedState);
if (rules.process(context)) {
event.setCancelled(true);
return;
}
break;
case LAVA:
case SPREAD:
// Consider everything else as a block spread
rules = wcfg.getRuleList().get(DefaultAttachments.BLOCK_SPREAD);
context = new BukkitContext(plugin, event);
context.setTargetBlock(event.getBlock().getState());
// Make a virtual source state
BlockState sourceState = event.getBlock().getState();
sourceState.setType(event.getCause() == IgniteCause.LAVA ? Material.LAVA : Material.FIRE);
context.setSourceBlock(sourceState);
// Make a virtual new state
placedState = event.getBlock().getState();
placedState.setType(Material.FIRE);
context.setPlacedBlock(placedState);
if (rules.process(context)) {
event.setCancelled(true);
return;
}
break;
case FIREBALL:
case LIGHTNING:
// Consider everything else as a block spread
rules = wcfg.getRuleList().get(DefaultAttachments.BLOCK_PLACE);
context = new BukkitContext(plugin, event);
context.setTargetBlock(event.getBlock().getState());
// Make a virtual new state
placedState = event.getBlock().getState();
placedState.setType(Material.FIRE);
context.setPlacedBlock(placedState);
if (rules.process(context)) {
event.setCancelled(true);
return;
}
break;
}
}
@EventHandler(priority = EventPriority.HIGH, ignoreCancelled = true)
public void onBlockBurn(BlockBurnEvent event) {
ConfigurationManager cfg = plugin.getGlobalStateManager();
WorldConfiguration wcfg = cfg.get(event.getBlock().getWorld());
// Fire stop toggle
if (wcfg.fireSpreadDisableToggle) {
Block block = event.getBlock();
event.setCancelled(true);
BukkitUtil.checkAndDestroyAround(block.getWorld(), block.getX(),
block.getY(), block.getZ(), BlockID.FIRE);
return;
}
// RuleLists
RuleSet rules = wcfg.getRuleList().get(DefaultAttachments.BLOCK_BREAK);
BukkitContext context = new BukkitContext(plugin, event);
BlockState virtualFireState = event.getBlock().getState();
virtualFireState.setType(Material.FIRE);
context.setSourceBlock(virtualFireState);
context.setTargetBlock(event.getBlock().getState());
if (rules.process(context)) {
event.setCancelled(true);
return;
}
}
@EventHandler(ignoreCancelled = true)
public void onBlockPhysics(BlockPhysicsEvent event) {
Block block = event.getBlock();
ConfigurationManager cfg = plugin.getGlobalStateManager();
WorldConfiguration wcfg = cfg.get(event.getBlock().getWorld());
// RuleLists
RuleSet rules = wcfg.getRuleList().get(DefaultAttachments.BLOCK_PHYSICS);
BukkitContext context = new BukkitContext(plugin, event);
context.setTargetBlock(event.getBlock().getState());
if (rules.process(context)) {
event.setCancelled(true);
return;
}
/* --- No short-circuit returns below this line --- */
// Sponges
SpongeApplicator spongeAppl = wcfg.getSpongeApplicator();
if (spongeAppl != null && block.getType() == Material.SPONGE) {
if (spongeAppl.isActiveSponge(block)) {
spongeAppl.placeWater(block);
} else {
spongeAppl.clearWater(block);
}
}
}
@EventHandler(priority = EventPriority.HIGH, ignoreCancelled = true)
public void onBlockPlace(BlockPlaceEvent event) {
Block blockPlaced = event.getBlock();
World world = blockPlaced.getWorld();
ConfigurationManager cfg = plugin.getGlobalStateManager();
WorldConfiguration wcfg = cfg.get(world);
// Sponges
SpongeApplicator spongeAppl = wcfg.getSpongeApplicator();
if (spongeAppl != null && spongeAppl.isActiveSponge(blockPlaced)) {
spongeAppl.clearWater(blockPlaced);
}
// RuleLists
RuleSet rules = wcfg.getRuleList().get(DefaultAttachments.BLOCK_PLACE);
BukkitContext context = new BukkitContext(plugin, event);
context.setSourceEntity(event.getPlayer());
context.setTargetBlock(event.getBlock().getState());
context.setPlacedBlock(event.getBlockReplacedState());
if (rules.process(context)) {
event.setCancelled(true);
return;
}
}
@EventHandler(priority = EventPriority.HIGH, ignoreCancelled = true)
public void onSignChange(SignChangeEvent event) {
Player player = event.getPlayer();
ConfigurationManager cfg = plugin.getGlobalStateManager();
WorldConfiguration wcfg = cfg.get(player.getWorld());
// RuleLists
RuleSet rules = wcfg.getRuleList().get(DefaultAttachments.BLOCK_INTERACT);
BukkitContext context = new BukkitContext(plugin, event);
context.setTargetBlock(event.getBlock().getState());
if (rules.process(context)) {
event.setCancelled(true);
return;
}
// Chest protection
if (wcfg.signChestProtection) {
if (event.getLine(0).equalsIgnoreCase("[Lock]")) {
if (event.getBlock().getTypeId() != BlockID.SIGN_POST) {
player.sendMessage(ChatColor.RED
+ "The [Lock] sign must be a sign post, not a wall sign.");
event.getBlock().breakNaturally();
event.setCancelled(true);
return;
}
if (!event.getLine(1).equalsIgnoreCase(player.getName())) {
player.sendMessage(ChatColor.RED
+ "The first owner line must be your name.");
event.getBlock().breakNaturally();
event.setCancelled(true);
return;
}
int below = event.getBlock().getRelative(0, -1, 0).getTypeId();
if (below == BlockID.TNT || below == BlockID.SAND
|| below == BlockID.GRAVEL || below == BlockID.SIGN_POST) {
player.sendMessage(ChatColor.RED
+ "That is not a safe block that you're putting this sign on.");
event.getBlock().breakNaturally();
event.setCancelled(true);
return;
}
event.setLine(0, "[Lock]");
player.sendMessage(ChatColor.YELLOW
+ "A chest or double chest above is now protected.");
}
} else if (!wcfg.disableSignChestProtectionCheck) {
if (event.getLine(0).equalsIgnoreCase("[Lock]")) {
player.sendMessage(ChatColor.RED
+ "WorldGuard's sign chest protection is disabled.");
event.getBlock().breakNaturally();
event.setCancelled(true);
return;
}
}
}
@EventHandler(priority = EventPriority.HIGH, ignoreCancelled = true)
public void onLeavesDecay(LeavesDecayEvent event) {
ConfigurationManager cfg = plugin.getGlobalStateManager();
WorldConfiguration wcfg = cfg.get(event.getBlock().getWorld());
// RuleLists
RuleSet rules = wcfg.getRuleList().get(DefaultAttachments.BLOCK_FADE);
BukkitContext context = new BukkitContext(plugin, event);
context.setTargetBlock(event.getBlock().getState());
if (rules.process(context)) {
event.setCancelled(true);
return;
}
}
@EventHandler(priority = EventPriority.HIGH, ignoreCancelled = true)
public void onBlockForm(BlockFormEvent event) {
ConfigurationManager cfg = plugin.getGlobalStateManager();
WorldConfiguration wcfg = cfg.get(event.getBlock().getWorld());
// RuleLists
RuleSet rules = wcfg.getRuleList().get(DefaultAttachments.BLOCK_FORM);
BukkitContext context = new BukkitContext(plugin, event);
context.setTargetBlock(event.getBlock().getState());
context.setPlacedBlock(event.getNewState());
if (rules.process(context)) {
event.setCancelled(true);
return;
}
}
@EventHandler(priority = EventPriority.HIGH, ignoreCancelled = true)
public void onBlockSpread(BlockSpreadEvent event) {
ConfigurationManager cfg = plugin.getGlobalStateManager();
WorldConfiguration wcfg = cfg.get(event.getBlock().getWorld());
// RuleLists
RuleSet rules = wcfg.getRuleList().get(DefaultAttachments.BLOCK_SPREAD);
BukkitContext context = new BukkitContext(plugin, event);
context.setSourceBlock(event.getSource().getState());
context.setTargetBlock(event.getBlock().getState());
context.setPlacedBlock(event.getNewState());
if (rules.process(context)) {
event.setCancelled(true);
return;
}
}
@EventHandler(priority = EventPriority.HIGH, ignoreCancelled = true)
public void onBlockFade(BlockFadeEvent event) {
ConfigurationManager cfg = plugin.getGlobalStateManager();
WorldConfiguration wcfg = cfg.get(event.getBlock().getWorld());
// RuleLists
RuleSet rules = wcfg.getRuleList().get(DefaultAttachments.BLOCK_FADE);
BukkitContext context = new BukkitContext(plugin, event);
context.setTargetBlock(event.getBlock().getState());
context.setPlacedBlock(event.getNewState());
if (rules.process(context)) {
event.setCancelled(true);
return;
}
}
@EventHandler(priority = EventPriority.HIGH, ignoreCancelled = true)
public void onBlockDispense(BlockDispenseEvent event) {
ConfigurationManager cfg = plugin.getGlobalStateManager();
WorldConfiguration wcfg = cfg.get(event.getBlock().getWorld());
// RuleLists
RuleSet rules = wcfg.getRuleList().get(DefaultAttachments.ITEM_DROP);
BukkitContext context = new BukkitContext(plugin, event);
context.setSourceBlock(event.getBlock().getState());
context.setItem(event.getItem());
if (rules.process(context)) {
event.setCancelled(true);
return;
}
}
}
@@ -0,0 +1,314 @@
// $Id$
/*
* WorldGuard
* Copyright (C) 2010 sk89q <http://www.sk89q.com>
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU 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 General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package com.sk89q.worldguard.bukkit;
import java.util.Iterator;
import org.bukkit.Location;
import org.bukkit.Material;
import org.bukkit.World;
import org.bukkit.block.Block;
import org.bukkit.block.BlockState;
import org.bukkit.entity.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.entity.CreatureSpawnEvent;
import org.bukkit.event.entity.CreeperPowerEvent;
import org.bukkit.event.entity.EntityChangeBlockEvent;
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.PlayerDeathEvent;
import org.bukkit.event.entity.EntityDeathEvent;
import org.bukkit.event.entity.EntityExplodeEvent;
import org.bukkit.event.entity.EntityInteractEvent;
import org.bukkit.event.entity.ExplosionPrimeEvent;
import org.bukkit.event.entity.PigZapEvent;
import org.bukkit.event.entity.PotionSplashEvent;
import com.sk89q.rulelists.DefaultAttachments;
import com.sk89q.rulelists.RuleSet;
import com.sk89q.worldguard.region.RegionManager;
import com.sk89q.worldguard.region.flags.DefaultFlag;
/**
* The listener for entity events.
*/
class WorldGuardEntityListener implements Listener {
private WorldGuardPlugin plugin;
/**
* Construct the listener.
*
* @param plugin WorldGuard plugin
*/
WorldGuardEntityListener(WorldGuardPlugin plugin) {
this.plugin = plugin;
}
/**
* Register the events.
*/
void registerEvents() {
plugin.getServer().getPluginManager().registerEvents(this, plugin);
}
@EventHandler(priority = EventPriority.HIGH, ignoreCancelled = true)
public void onEntityInteract(EntityInteractEvent event) {
ConfigurationManager cfg = plugin.getGlobalStateManager();
WorldConfiguration wcfg = cfg.get(event.getEntity().getWorld());
// RuleLists
RuleSet rules = wcfg.getRuleList().get(DefaultAttachments.BLOCK_INTERACT);
BukkitContext context = new BukkitContext(plugin, event);
context.setSourceEntity(event.getEntity());
context.setTargetBlock(event.getBlock().getState());
if (rules.process(context)) {
event.setCancelled(true);
return;
}
}
@EventHandler(priority = EventPriority.HIGH)
public void onEntityDeath(EntityDeathEvent event) {
ConfigurationManager cfg = plugin.getGlobalStateManager();
WorldConfiguration wcfg = cfg.get(event.getEntity().getWorld());
/* --- No short-circuit returns below this line --- */
// RuleLists
RuleSet rules = wcfg.getRuleList().get(DefaultAttachments.ENTITY_DEATH);
BukkitContext context = new BukkitContext(plugin, event);
context.setTargetEntity(event.getEntity());
// Set a message if it's a death from a player
if (event instanceof PlayerDeathEvent) {
context.setMessage(((PlayerDeathEvent) event).getDeathMessage());
}
rules.process(context);
// Set the message back
if (event instanceof PlayerDeathEvent) {
((PlayerDeathEvent) event).setDeathMessage(context.getMessage());
}
}
@EventHandler(priority = EventPriority.HIGH, ignoreCancelled = true)
public void onEntityDamage(EntityDamageEvent event) {
ConfigurationManager cfg = plugin.getGlobalStateManager();
WorldConfiguration wcfg = cfg.get(event.getEntity().getWorld());
// Redirect damage done by an entity
if (event instanceof EntityDamageByEntityEvent) {
// RuleLists
RuleSet rules = wcfg.getRuleList().get(DefaultAttachments.ENTITY_DAMAGE);
BukkitContext context = new BukkitContext(plugin, event);
context.setSourceEntity(((EntityDamageByEntityEvent) event).getDamager());
context.setTargetEntity(event.getEntity());
if (rules.process(context)) {
event.setCancelled(true);
return;
}
// Redirect damage done by blocks
} else if (event instanceof EntityDamageByBlockEvent) {
// RuleLists
RuleSet rules = wcfg.getRuleList().get(DefaultAttachments.ENTITY_DAMAGE);
BukkitContext context = new BukkitContext(plugin, event);
Block damager = ((EntityDamageByBlockEvent) event).getDamager();
if (damager != null) { // Should NOT be null!
context.setSourceBlock(damager.getState());
}
context.setTargetEntity(event.getEntity());
if (rules.process(context)) {
event.setCancelled(true);
return;
}
// Other damage
} else {
// RuleLists
RuleSet rules = wcfg.getRuleList().get(DefaultAttachments.ENTITY_DAMAGE);
BukkitContext context = new BukkitContext(plugin, event);
context.setTargetEntity(event.getEntity());
if (rules.process(context)) {
event.setCancelled(true);
return;
}
}
}
@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());
// RuleLists
RuleSet rules = wcfg.getRuleList().get(DefaultAttachments.ENTITY_IGNITE);
BukkitContext context = new BukkitContext(plugin, event);
context.setTargetEntity(entity);
if (rules.process(context)) {
event.setCancelled(true);
return;
}
}
@EventHandler(priority = EventPriority.HIGH, ignoreCancelled = true)
public void onEntityExplode(EntityExplodeEvent event) {
ConfigurationManager cfg = plugin.getGlobalStateManager();
Location l = event.getLocation();
World world = l.getWorld();
WorldConfiguration wcfg = cfg.get(world);
// RuleLists
RuleSet rules = wcfg.getRuleList().get(DefaultAttachments.ENTITY_EXPLODE);
BukkitContext context = new BukkitContext(plugin, event);
context.setTargetEntity(event.getEntity());
if (rules.process(context)) {
event.setCancelled(true);
return;
}
/* --- No short-circuit returns below this line --- */
// Now apply RuleLists for each block
Iterator<Block> iter = event.blockList().iterator();
while (iter.hasNext()) {
Block block = iter.next();
rules = wcfg.getRuleList().get(DefaultAttachments.BLOCK_BREAK);
context = new BukkitContext(plugin, event);
context.setSourceEntity(event.getEntity());
context.setTargetBlock(block.getState());
rules.process(context);
if (context.isCancelled()) {
iter.remove();
}
}
}
@EventHandler(priority = EventPriority.HIGH, ignoreCancelled = true)
public void onExplosionPrime(ExplosionPrimeEvent event) {
ConfigurationManager cfg = plugin.getGlobalStateManager();
WorldConfiguration wcfg = cfg.get(event.getEntity().getWorld());
// RuleLists
RuleSet rules = wcfg.getRuleList().get(DefaultAttachments.ENTITY_EXPLODE);
BukkitContext context = new BukkitContext(plugin, event);
context.setTargetEntity(event.getEntity());
if (rules.process(context)) {
event.setCancelled(true);
return;
}
}
@EventHandler(priority = EventPriority.HIGH, ignoreCancelled = true)
public void onCreatureSpawn(CreatureSpawnEvent event) {
ConfigurationManager cfg = plugin.getGlobalStateManager();
WorldConfiguration wcfg = cfg.get(event.getEntity().getWorld());
// RuleLists
RuleSet rules = wcfg.getRuleList().get(DefaultAttachments.ENTITY_SPAWN);
BukkitContext context = new BukkitContext(plugin, event);
context.setTargetEntity(event.getEntity());
if (rules.process(context)) {
event.setCancelled(true);
return;
}
}
@EventHandler(priority = EventPriority.HIGH, ignoreCancelled = true)
public void onPigZap(PigZapEvent event) {
ConfigurationManager cfg = plugin.getGlobalStateManager();
WorldConfiguration wcfg = cfg.get(event.getEntity().getWorld());
// RuleLists
RuleSet rules = wcfg.getRuleList().get(DefaultAttachments.ENTITY_STRIKE);
BukkitContext context = new BukkitContext(plugin, event);
context.setTargetEntity(event.getEntity());
if (rules.process(context)) {
event.setCancelled(true);
return;
}
}
@EventHandler(priority = EventPriority.HIGH, ignoreCancelled = true)
public void onCreeperPower(CreeperPowerEvent event) {
ConfigurationManager cfg = plugin.getGlobalStateManager();
WorldConfiguration wcfg = cfg.get(event.getEntity().getWorld());
// RuleLists
RuleSet rules = wcfg.getRuleList().get(DefaultAttachments.ENTITY_STRIKE);
BukkitContext context = new BukkitContext(plugin, event);
context.setTargetEntity(event.getEntity());
if (rules.process(context)) {
event.setCancelled(true);
return;
}
}
@EventHandler(priority = EventPriority.HIGH, ignoreCancelled = true)
public void onEntityChangeBlock(EntityChangeBlockEvent event) {
Entity entity = event.getEntity();
ConfigurationManager cfg = plugin.getGlobalStateManager();
WorldConfiguration wcfg = cfg.get(entity.getWorld());
// RuleLists
RuleSet rules = wcfg.getRuleList().get(event.getTo() == Material.AIR ?
DefaultAttachments.BLOCK_BREAK : DefaultAttachments.BLOCK_PLACE);
BukkitContext context = new BukkitContext(plugin, event);
context.setSourceEntity(entity);
BlockState newState = event.getBlock().getState(); // This event is lame
newState.setType(event.getTo()); // Need to construct our own BlockState
context.setTargetBlock(event.getBlock().getState());
context.setPlacedBlock(newState);
if (rules.process(context)) {
event.setCancelled(true);
return;
}
}
@EventHandler(ignoreCancelled = true)
public void onPotionSplash(PotionSplashEvent event) {
RegionManager global = plugin.getGlobalRegionManager();
/* --- No short-circuit returns below this line --- */
int blockedEntities = 0;
for (LivingEntity e : event.getAffectedEntities()) {
if (!global.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);
}
}
}
@@ -0,0 +1,96 @@
// $Id$
/*
* WorldGuard
* Copyright (C) 2010 sk89q <http://www.sk89q.com>
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU 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 General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package com.sk89q.worldguard.bukkit;
import org.bukkit.World;
import org.bukkit.block.Block;
import org.bukkit.entity.Hanging;
import org.bukkit.event.EventHandler;
import org.bukkit.event.EventPriority;
import org.bukkit.event.Listener;
import org.bukkit.event.hanging.HangingBreakByEntityEvent;
import org.bukkit.event.hanging.HangingBreakEvent;
import org.bukkit.event.hanging.HangingPlaceEvent;
import com.sk89q.rulelists.DefaultAttachments;
import com.sk89q.rulelists.RuleSet;
/**
* Listener for hanging entity events.
*/
class WorldGuardHangingListener implements Listener {
private WorldGuardPlugin plugin;
/**
* Construct the listener.
*
* @param plugin WorldGuard plugin
*/
WorldGuardHangingListener(WorldGuardPlugin plugin) {
this.plugin = plugin;
}
/**
* Register events.
*/
void registerEvents() {
plugin.getServer().getPluginManager().registerEvents(this, plugin);
}
@EventHandler(priority = EventPriority.HIGH, ignoreCancelled = true)
public void onHangingingBreak(HangingBreakEvent event) {
Hanging hanging = event.getEntity();
World world = hanging.getWorld();
ConfigurationManager cfg = plugin.getGlobalStateManager();
WorldConfiguration wcfg = cfg.get(world);
// RuleLists
RuleSet rules = wcfg.getRuleList().get(DefaultAttachments.ENTITY_DAMAGE);
BukkitContext context = new BukkitContext(plugin, event);
if (event instanceof HangingBreakByEntityEvent) {
context.setSourceEntity(((HangingBreakByEntityEvent) event).getRemover());
}
context.setTargetEntity(event.getEntity());
if (rules.process(context)) {
event.setCancelled(true);
return;
}
}
@EventHandler(priority = EventPriority.HIGH, ignoreCancelled = true)
public void onHangingPlace(HangingPlaceEvent event) {
Block placedOn = event.getBlock();
World world = placedOn.getWorld();
ConfigurationManager cfg = plugin.getGlobalStateManager();
WorldConfiguration wcfg = cfg.get(world);
// RuleLists
RuleSet rules = wcfg.getRuleList().get(DefaultAttachments.ENTITY_SPAWN);
BukkitContext context = new BukkitContext(plugin, event);
context.setSourceEntity(event.getPlayer());
context.setTargetEntity(event.getEntity());
if (rules.process(context)) {
event.setCancelled(true);
return;
}
}
}
@@ -0,0 +1,98 @@
// $Id$
/*
* WorldGuard
* Copyright (C) 2010 sk89q <http://www.sk89q.com>
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU 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 General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package com.sk89q.worldguard.bukkit;
import org.bukkit.World;
import org.bukkit.block.Block;
import org.bukkit.entity.Painting;
import org.bukkit.event.EventHandler;
import org.bukkit.event.EventPriority;
import org.bukkit.event.Listener;
import org.bukkit.event.painting.PaintingBreakByEntityEvent;
import org.bukkit.event.painting.PaintingBreakEvent;
import org.bukkit.event.painting.PaintingPlaceEvent;
import com.sk89q.rulelists.DefaultAttachments;
import com.sk89q.rulelists.RuleSet;
/**
* Listener for painting related events. This event is deprecated and it is provided for
* compatibility with older versions of Bukkit.
*/
@Deprecated
public class WorldGuardPaintingListener implements Listener {
private WorldGuardPlugin plugin;
/**
* Construct the listener.
*
* @param plugin WorldGuard plugin
*/
WorldGuardPaintingListener(WorldGuardPlugin plugin) {
this.plugin = plugin;
}
/**
* Register events.
*/
void registerEvents() {
plugin.getServer().getPluginManager().registerEvents(this, plugin);
}
@EventHandler(priority = EventPriority.HIGH, ignoreCancelled = true)
public void onPaintingBreak(PaintingBreakEvent event) {
Painting painting = event.getPainting();
World world = painting.getWorld();
ConfigurationManager cfg = plugin.getGlobalStateManager();
WorldConfiguration wcfg = cfg.get(world);
// RuleLists
RuleSet rules = wcfg.getRuleList().get(DefaultAttachments.ENTITY_DAMAGE);
BukkitContext context = new BukkitContext(plugin, event);
if (event instanceof PaintingBreakByEntityEvent) {
context.setSourceEntity(((PaintingBreakByEntityEvent) event).getRemover());
}
context.setTargetEntity(event.getPainting());
if (rules.process(context)) {
event.setCancelled(true);
return;
}
}
@EventHandler(priority = EventPriority.HIGH, ignoreCancelled = true)
public void onPaintingPlace(PaintingPlaceEvent event) {
Block placedOn = event.getBlock();
World world = placedOn.getWorld();
ConfigurationManager cfg = plugin.getGlobalStateManager();
WorldConfiguration wcfg = cfg.get(world);
// RuleLists
RuleSet rules = wcfg.getRuleList().get(DefaultAttachments.ENTITY_SPAWN);
BukkitContext context = new BukkitContext(plugin, event);
context.setSourceEntity(event.getPlayer());
context.setTargetEntity(event.getPainting());
if (rules.process(context)) {
event.setCancelled(true);
return;
}
}
}
@@ -0,0 +1,330 @@
// $Id$
/*
* WorldGuard
* Copyright (C) 2010 sk89q <http://www.sk89q.com>
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU 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 General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package com.sk89q.worldguard.bukkit;
import org.bukkit.ChatColor;
import org.bukkit.World;
import org.bukkit.block.Block;
import org.bukkit.entity.Player;
import org.bukkit.event.Event.Result;
import org.bukkit.event.EventHandler;
import org.bukkit.event.EventPriority;
import org.bukkit.event.Listener;
import org.bukkit.event.entity.PlayerDeathEvent;
import org.bukkit.event.player.AsyncPlayerChatEvent;
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.PlayerInteractEvent;
import org.bukkit.event.player.PlayerJoinEvent;
import org.bukkit.event.player.PlayerLoginEvent;
import org.bukkit.event.player.PlayerMoveEvent;
import org.bukkit.event.player.PlayerPickupItemEvent;
import org.bukkit.event.player.PlayerQuitEvent;
import org.bukkit.event.player.PlayerRespawnEvent;
import org.bukkit.inventory.ItemStack;
import org.bukkit.plugin.PluginManager;
import com.sk89q.rulelists.DefaultAttachments;
import com.sk89q.rulelists.RuleSet;
/**
* Listener for player events.
*/
class WorldGuardPlayerListener implements Listener {
private WorldGuardPlugin plugin;
/**
* Construct the listener.
*
* @param plugin WorldGuard plugin
*/
WorldGuardPlayerListener(WorldGuardPlugin plugin) {
this.plugin = plugin;
}
/**
* Register the events.
*/
void registerEvents() {
final PluginManager pm = plugin.getServer().getPluginManager();
pm.registerEvents(this, plugin);
if (plugin.getGlobalStateManager().usePlayerMove) {
pm.registerEvents(new PlayerMoveHandler(), plugin);
}
}
/**
* Listener just for {@link PlayerMoveEvent}. This handler may not always be
* registered for performance reasons.
*/
class PlayerMoveHandler implements Listener {
}
@EventHandler
public void onPlayerJoin(PlayerJoinEvent event) {
Player player = event.getPlayer();
World world = player.getWorld();
ConfigurationManager cfg = plugin.getGlobalStateManager();
WorldConfiguration wcfg = cfg.get(world);
/* --- No short-circuit returns below this line --- */
if (wcfg.fireSpreadDisableToggle) {
player.sendMessage(ChatColor.YELLOW
+ "Fire spread is currently globally disabled for this world.");
}
// RuleLists
RuleSet rules = wcfg.getRuleList().get(DefaultAttachments.PLAYER_JOIN);
BukkitContext context = new BukkitContext(plugin, event);
context.setTargetEntity(player);
rules.process(context);
}
@EventHandler(ignoreCancelled = true)
public void onPlayerChat(AsyncPlayerChatEvent event) {
Player player = event.getPlayer();
WorldConfiguration wcfg = plugin.getGlobalStateManager().get(player.getWorld());
// RuleLists
RuleSet rules = wcfg.getRuleList().get(DefaultAttachments.CHAT);
BukkitContext context = new BukkitContext(plugin, event);
context.setSourceEntity(event.getPlayer());
context.setMessage(event.getMessage());
if (rules.process(context)) {
event.setCancelled(true);
return;
}
// Put back the chat
event.setMessage(context.getMessage());
}
@EventHandler(ignoreCancelled = true)
public void onPlayerLogin(PlayerLoginEvent event) {
Player player = event.getPlayer();
ConfigurationManager cfg = plugin.getGlobalStateManager();
/* --- No short-circuit returns below this line --- */
// Host keys
String hostKey = cfg.hostKeys.get(player.getName().toLowerCase());
if (hostKey != null) {
String hostname = event.getHostname();
int colonIndex = hostname.indexOf(':');
if (colonIndex != -1) {
hostname = hostname.substring(0, colonIndex);
}
if (!hostname.equals(hostKey)) {
event.disallow(PlayerLoginEvent.Result.KICK_OTHER,
"You did not join with the valid host key!");
plugin.getLogger().warning("WorldGuard host key check: " +
player.getName() + " joined with '" + hostname +
"' but '" + hostKey + "' was expected. Kicked!");
}
}
}
@EventHandler
public void onPlayerQuit(PlayerQuitEvent event) {
Player player = event.getPlayer();
World world = player.getWorld();
ConfigurationManager cfg = plugin.getGlobalStateManager();
WorldConfiguration wcfg = cfg.get(world);
/* --- No short-circuit returns below this line --- */
// RuleLists
RuleSet rules = wcfg.getRuleList().get(DefaultAttachments.PLAYER_QUIT);
BukkitContext context = new BukkitContext(plugin, event);
context.setSourceEntity(player);
rules.process(context);
// Cleanup
cfg.forgetPlayer(plugin.wrapPlayer(player));
plugin.forgetPlayer(player);
}
@EventHandler(priority = EventPriority.HIGH)
public void onPlayerInteract(PlayerInteractEvent event) {
Player player = event.getPlayer();
ConfigurationManager cfg = plugin.getGlobalStateManager();
WorldConfiguration wcfg = cfg.get(player.getWorld());
/* --- No short-circuit returns below this line --- */
// RuleLists
RuleSet rules;
BukkitContext context;
// Send one for the block
Block block = event.getClickedBlock();
if (block != null) {
rules = wcfg.getRuleList().get(DefaultAttachments.BLOCK_INTERACT);
context = new BukkitContext(plugin, event);
context.setSourceEntity(player);
context.setTargetBlock(event.getClickedBlock().getState());
if (rules.process(context)) {
event.setUseInteractedBlock(Result.DENY);
}
}
// Send one for the item in the end
ItemStack heldItem = event.getPlayer().getItemInHand();
if (heldItem != null) {
rules = wcfg.getRuleList().get(DefaultAttachments.ITEM_USE);
context = new BukkitContext(plugin, event);
context.setSourceEntity(event.getPlayer());
context.setItem(heldItem);
if (rules.process(context)) {
event.setUseItemInHand(Result.DENY);
}
}
}
@EventHandler(priority = EventPriority.HIGH, ignoreCancelled = true)
public void onPlayerDropItem(PlayerDropItemEvent event) {
ConfigurationManager cfg = plugin.getGlobalStateManager();
WorldConfiguration wcfg = cfg.get(event.getPlayer().getWorld());
Player player = event.getPlayer();
// RuleLists
RuleSet rules = wcfg.getRuleList().get(DefaultAttachments.ITEM_DROP);
BukkitContext context = new BukkitContext(plugin, event);
context.setSourceEntity(player);
context.setItem(event.getItemDrop().getItemStack());
if (rules.process(context)) {
event.setCancelled(true);
return;
}
}
@EventHandler(priority = EventPriority.HIGH, ignoreCancelled = true)
public void onPlayerPickupItem(PlayerPickupItemEvent event) {
ConfigurationManager cfg = plugin.getGlobalStateManager();
WorldConfiguration wcfg = cfg.get(event.getPlayer().getWorld());
// RuleLists
RuleSet rules = wcfg.getRuleList().get(DefaultAttachments.ITEM_PICKUP);
BukkitContext context = new BukkitContext(plugin, event);
context.setSourceEntity(event.getPlayer());
context.setItem(event.getItem().getItemStack());
if (rules.process(context)) {
event.setCancelled(true);
return;
}
}
@EventHandler(priority = EventPriority.HIGH, ignoreCancelled = true)
public void onPlayerDeath(PlayerDeathEvent event) {
Player player = event.getEntity();
ConfigurationManager cfg = plugin.getGlobalStateManager();
WorldConfiguration wcfg = cfg.get(player.getWorld());
/* --- No short-circuit returns below this line --- */
// RuleLists
RuleSet rules = wcfg.getRuleList().get(DefaultAttachments.ENTITY_DEATH);
BukkitContext context = new BukkitContext(plugin, event);
context.setTargetEntity(player);
rules.process(context);
}
@EventHandler(priority = EventPriority.HIGH, ignoreCancelled = true)
public void onPlayerBucketFill(PlayerBucketFillEvent event) {
Player player = event.getPlayer();
World world = player.getWorld();
ConfigurationManager cfg = plugin.getGlobalStateManager();
WorldConfiguration wcfg = cfg.get(world);
// RuleLists
RuleSet rules = wcfg.getRuleList().get(DefaultAttachments.ITEM_USE);
BukkitContext context = new BukkitContext(plugin, event);
context.setSourceEntity(event.getPlayer());
context.setItem(event.getItemStack());
if (rules.process(context)) {
event.setCancelled(true);
return;
}
}
@EventHandler(priority = EventPriority.HIGH, ignoreCancelled = true)
public void onPlayerBucketEmpty(PlayerBucketEmptyEvent event) {
Player player = event.getPlayer();
World world = player.getWorld();
ConfigurationManager cfg = plugin.getGlobalStateManager();
WorldConfiguration wcfg = cfg.get(world);
// RuleLists
RuleSet rules = wcfg.getRuleList().get(DefaultAttachments.ITEM_USE);
BukkitContext context = new BukkitContext(plugin, event);
context.setSourceEntity(event.getPlayer());
context.setItem(event.getItemStack());
if (rules.process(context)) {
event.setCancelled(true);
return;
}
}
@EventHandler(priority = EventPriority.HIGHEST)
public void onPlayerRespawn(PlayerRespawnEvent event) {
Player player = event.getPlayer();
ConfigurationManager cfg = plugin.getGlobalStateManager();
WorldConfiguration wcfg = cfg.get(player.getWorld());
/* --- No short-circuit returns below this line --- */
// RuleLists
RuleSet rules = wcfg.getRuleList().get(DefaultAttachments.PLAYER_RESPAWN);
BukkitContext context = new BukkitContext(plugin, event);
context.setSourceEntity(event.getPlayer());
rules.process(context);
}
@EventHandler(priority = EventPriority.HIGH, ignoreCancelled = true)
public void onPlayerBedEnter(PlayerBedEnterEvent event) {
Player player = event.getPlayer();
ConfigurationManager cfg = plugin.getGlobalStateManager();
WorldConfiguration wcfg = cfg.get(player.getWorld());
// RuleLists
RuleSet rules = wcfg.getRuleList().get(DefaultAttachments.BLOCK_INTERACT);
BukkitContext context = new BukkitContext(plugin, event);
context.setSourceEntity(player);
context.setTargetBlock(event.getBed().getState());
if (rules.process(context)) {
event.setCancelled(true);
return;
}
}
}
@@ -0,0 +1,933 @@
// $Id$
/*
* WorldGuard
* Copyright (C) 2010 sk89q <http://www.sk89q.com>
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU 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 General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package com.sk89q.worldguard.bukkit;
import static com.sk89q.worldguard.bukkit.BukkitUtil.hasHangingEvent;
import java.io.File;
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 org.bukkit.ChatColor;
import org.bukkit.Location;
import org.bukkit.World;
import org.bukkit.World.Environment;
import org.bukkit.block.Block;
import org.bukkit.command.Command;
import org.bukkit.command.CommandSender;
import org.bukkit.command.ConsoleCommandSender;
import org.bukkit.entity.Player;
import org.bukkit.event.world.WorldLoadEvent;
import org.bukkit.permissions.Permissible;
import org.bukkit.plugin.Plugin;
import org.bukkit.plugin.java.JavaPlugin;
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.rebar.bukkit.VirtualRebarPlugin;
import com.sk89q.rebar.config.ConfigurationException;
import com.sk89q.rebar.config.YamlConfiguration;
import com.sk89q.rebar.config.YamlConfigurationResource;
import com.sk89q.rulelists.Action;
import com.sk89q.rulelists.Criteria;
import com.sk89q.rulelists.DefaultAttachments;
import com.sk89q.rulelists.DefinitionManager;
import com.sk89q.rulelists.ResolverManager;
import com.sk89q.rulelists.RuleListsManager;
import com.sk89q.wepif.PermissionsResolverManager;
import com.sk89q.worldedit.bukkit.WorldEditPlugin;
import com.sk89q.worldguard.LocalPlayer;
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.definitions.BlockCriteriaLoader;
import com.sk89q.worldguard.bukkit.definitions.CancelActionLoader;
import com.sk89q.worldguard.bukkit.definitions.DamageCriteriaLoader;
import com.sk89q.worldguard.bukkit.definitions.EntityCriteriaLoader;
import com.sk89q.worldguard.bukkit.definitions.FlagCriteriaLoader;
import com.sk89q.worldguard.bukkit.definitions.ItemCriteriaLoader;
import com.sk89q.worldguard.bukkit.definitions.PermissionCriteriaLoader;
import com.sk89q.worldguard.bukkit.definitions.PhenomenonCriteriaLoader;
import com.sk89q.worldguard.bukkit.definitions.RegionCriteriaLoader;
import com.sk89q.worldguard.bukkit.definitions.SetBlockActionLoader;
import com.sk89q.worldguard.bukkit.definitions.SetDropActionLoader;
import com.sk89q.worldguard.bukkit.definitions.SpawnCriteriaLoader;
import com.sk89q.worldguard.bukkit.definitions.TellActionLoader;
import com.sk89q.worldguard.bukkit.definitions.UpdateEntityActionLoader;
import com.sk89q.worldguard.bukkit.definitions.UpdateItemActionLoader;
import com.sk89q.worldguard.bukkit.definitions.SetMessageActionLoader;
import com.sk89q.worldguard.bukkit.definitions.UpdateWorldActionLoader;
import com.sk89q.worldguard.bukkit.definitions.WeatherCriteriaLoader;
import com.sk89q.worldguard.bukkit.resolvers.BlockResolver;
import com.sk89q.worldguard.bukkit.resolvers.EntityResolver;
import com.sk89q.worldguard.bukkit.resolvers.ItemStackSlotResolver;
import com.sk89q.worldguard.bukkit.resolvers.PlacedBlockResolver;
import com.sk89q.worldguard.bukkit.resolvers.PlayerItemStackSlotResolver;
import com.sk89q.worldguard.bukkit.resolvers.PlayerItemStackSlotResolver.Slot;
import com.sk89q.worldguard.bukkit.resolvers.SourceBlockResolver;
import com.sk89q.worldguard.bukkit.resolvers.SourceEntityResolver;
import com.sk89q.worldguard.bukkit.resolvers.TargetBlockResolver;
import com.sk89q.worldguard.bukkit.resolvers.TargetEntityResolver;
import com.sk89q.worldguard.region.RegionManager;
import com.sk89q.worldguard.region.indices.RegionIndex;
/**
* The main class for WorldGuard as a Bukkit plugin.
*/
public class WorldGuardPlugin extends JavaPlugin {
private final CommandsManager<CommandSender> commands;
private final RegionManager globalRegionManager;
private final ConfigurationManager configuration;
private RuleListsManager ruleListsManager;
private RegionQueryCache regionCache;
private final LagStopMode lagStopper;
private WorldGuardWorldListener worldListener;
/**
* Do initial loading of WorldGuard. Only called once. {@link #onEnable()} will be
* called when WorldGuard is enabled.
*/
public WorldGuardPlugin() {
configuration = new ConfigurationManager(this);
globalRegionManager = new RegionManager(this);
lagStopper = new LagStopMode(this);
final WorldGuardPlugin plugin = this;
commands = new CommandsManager<CommandSender>() {
@Override
public boolean hasPermission(CommandSender player, String perm) {
return plugin.hasPermission(player, perm);
}
};
}
@SuppressWarnings("deprecation")
@Override
public void onEnable() {
// We don't require Rebar yet
VirtualRebarPlugin.setup(this);
// Set up RuleLists
ruleListsManager = new RuleListsManager();
registerRuleList();
// Setup the cache
regionCache = new RegionQueryCache(this);
// Set the proper command injector
commands.setInjector(new SimpleInjector(this));
// Register command classes
final CommandsManagerRegistration reg = new CommandsManagerRegistration(this, commands);
reg.register(ToggleCommands.class);
reg.register(ProtectionCommands.class);
getServer().getScheduler().scheduleSyncDelayedTask(this, new Runnable() {
@Override
public void run() {
if (!getGlobalStateManager().hasCommandBookGodMode()) {
reg.register(GeneralCommands.class);
}
}
}, 0L);
// Need to create the plugins/WorldGuard folder
getDataFolder().mkdirs();
PermissionsResolverManager.initialize(this);
// Load the configuration
configuration.load();
globalRegionManager.preload();
// Register events
(new WorldGuardPlayerListener(this)).registerEvents();
(new WorldGuardBlockListener(this)).registerEvents();
(new WorldGuardEntityListener(this)).registerEvents();
(new WorldGuardWeatherListener(this)).registerEvents();
(new WorldGuardVehicleListener(this)).registerEvents();
(new WorldGuardServerListener(this)).registerEvents();
(worldListener = new WorldGuardWorldListener(this)).registerEvents();
lagStopper.registerEvents();
// Initialization
simulateWorldLoad();
if (hasHangingEvent()) {
(new WorldGuardHangingListener(this)).registerEvents();
} else {
(new WorldGuardPaintingListener(this)).registerEvents();
}
configuration.updateCommandBookGodMode();
}
@Override
public void onDisable() {
globalRegionManager.unload();
configuration.unload();
this.getServer().getScheduler().cancelTasks(this);
}
@Override
public boolean onCommand(CommandSender sender, Command cmd, String label,
String[] args) {
try {
commands.execute(cmd.getName(), args, sender, sender);
} catch (CommandPermissionsException e) {
sender.sendMessage(ChatColor.RED + "You don't have permission.");
} catch (MissingNestedCommandException e) {
sender.sendMessage(ChatColor.RED + e.getUsage());
} catch (CommandUsageException e) {
sender.sendMessage(ChatColor.RED + e.getMessage());
sender.sendMessage(ChatColor.RED + e.getUsage());
} catch (WrappedCommandException e) {
if (e.getCause() instanceof NumberFormatException) {
sender.sendMessage(ChatColor.RED + "Number expected, string received instead.");
} else {
sender.sendMessage(ChatColor.RED + "An error has occurred. See console.");
e.printStackTrace();
}
} catch (CommandException e) {
sender.sendMessage(ChatColor.RED + e.getMessage());
}
return true;
}
/**
* Dispatch {@link WorldLoadEvent}s to the world listener.
*/
public void simulateWorldLoad() {
for (World world : getServer().getWorlds()) {
WorldLoadEvent event = new WorldLoadEvent(world);
worldListener.onWorldLoad(event);
}
}
/**
* Get the GlobalRegionManager.
*
* @return The plugin's global region manager
*/
public RegionManager getGlobalRegionManager() {
return globalRegionManager;
}
/**
* Get the WorldGuard Configuration.
*
* @return ConfigurationManager
* @deprecated Use {@link #getGlobalStateManager()} instead
*/
@Deprecated
public ConfigurationManager getGlobalConfiguration() {
return getGlobalStateManager();
}
/**
* Get the global ConfigurationManager.
* USe this to access global configuration values and per-world configuration values.
* @return The global ConfigurationManager
*/
public ConfigurationManager getGlobalStateManager() {
return configuration;
}
/**
* Get the rules list manager.
*
* @return rule lists manager
*/
public RuleListsManager getRulesListManager() {
return ruleListsManager;
}
/**
* Get the region query cache.
*
* @return region query cache
*/
public RegionQueryCache getRegionCache() {
return regionCache;
}
/**
* Get the built-in rules.
*
* @return built-in rules
* @throws ConfigurationException on config error
* @throws IOException on I/O exception
*/
public YamlConfiguration getBuiltInRules() throws IOException, ConfigurationException {
YamlConfiguration rules = new YamlConfigurationResource(getClass(),
"/defaults/builtin_rules.yml");
rules.load();
return rules;
}
/**
* Register RuleList resolvers, criterion, and actions.
*/
private void registerRuleList() {
DefaultAttachments.registerWith(ruleListsManager.getAttachments());
// Subject resolvers
ResolverManager resolvers = ruleListsManager.getResolvers();
resolvers.register(BlockResolver.class, "source", new SourceBlockResolver());
resolvers.register(BlockResolver.class, "target", new TargetBlockResolver());
resolvers.register(BlockResolver.class, "placed", new PlacedBlockResolver());
resolvers.register(EntityResolver.class, "source", new SourceEntityResolver());
resolvers.register(EntityResolver.class, "target", new TargetEntityResolver());
resolvers.register(ItemStackSlotResolver.class, "held", new PlayerItemStackSlotResolver(Slot.HELD));
resolvers.register(ItemStackSlotResolver.class, "helmet", new PlayerItemStackSlotResolver(Slot.HELMET));
resolvers.register(ItemStackSlotResolver.class, "chestplate", new PlayerItemStackSlotResolver(Slot.CHESTPLATE));
resolvers.register(ItemStackSlotResolver.class, "leggings", new PlayerItemStackSlotResolver(Slot.LEGGINGS));
resolvers.register(ItemStackSlotResolver.class, "boots", new PlayerItemStackSlotResolver(Slot.BOOTS));
// Criterion
DefinitionManager<Criteria<?>> criterion = ruleListsManager.getCriterion();
criterion.register("match-block", new BlockCriteriaLoader(ruleListsManager));
criterion.register("match-item", new ItemCriteriaLoader(ruleListsManager));
criterion.register("match-entity", new EntityCriteriaLoader(ruleListsManager));
criterion.register("match-damage", new DamageCriteriaLoader());
criterion.register("match-spawn", new SpawnCriteriaLoader());
criterion.register("match-phenomenon", new PhenomenonCriteriaLoader());
criterion.register("match-weather", new WeatherCriteriaLoader());
criterion.register("region-of", new RegionCriteriaLoader(ruleListsManager));
criterion.register("has-flag", new FlagCriteriaLoader(this, ruleListsManager));
criterion.register("has-permission", new PermissionCriteriaLoader(this, ruleListsManager));
// Actions
DefinitionManager<Action<?>> actions = ruleListsManager.getActions();
actions.register("cancel", new CancelActionLoader());
actions.register("tell", new TellActionLoader(ruleListsManager));
actions.register("update-item", new UpdateItemActionLoader(ruleListsManager));
actions.register("update-world", new UpdateWorldActionLoader());
actions.register("update-entity", new UpdateEntityActionLoader(this, ruleListsManager));
actions.register("set-message", new SetMessageActionLoader(ruleListsManager));
actions.register("set-drop", new SetDropActionLoader());
actions.register("set-block", new SetBlockActionLoader(ruleListsManager));
}
/**
* Check whether a player is in a group.
* This calls the corresponding method in PermissionsResolverManager
*
* @param player The player to check
* @param group The group
* @return whether {@code player} is in {@code group}
*/
public boolean inGroup(Player player, String group) {
try {
return PermissionsResolverManager.getInstance().inGroup(player, group);
} catch (Throwable t) {
t.printStackTrace();
return false;
}
}
/**
* Get the groups of a player.
* This calls the corresponding method in PermissionsResolverManager.
* @param player The player to check
* @return The names of each group the playe is in.
*/
public String[] getGroups(Player player) {
try {
return PermissionsResolverManager.getInstance().getGroups(player);
} catch (Throwable t) {
t.printStackTrace();
return new String[0];
}
}
/**
* Gets the name of a command sender. This is a unique name and this
* method should never return a "display name".
*
* @param sender The sender to get the name of
* @return The unique name of the sender.
*/
public String toUniqueName(CommandSender sender) {
if (sender instanceof ConsoleCommandSender) {
return "*Console*";
} else {
return sender.getName();
}
}
/**
* Gets the name of a command sender. This play be a display name.
*
* @param sender The CommandSender to get the name of.
* @return The name of the given sender
*/
public String toName(CommandSender sender) {
if (sender instanceof ConsoleCommandSender) {
return "*Console*";
} else if (sender instanceof Player) {
return ((Player) sender).getDisplayName();
} else {
return sender.getName();
}
}
/**
* Checks permissions.
*
* @param sender The sender to check the permission on.
* @param perm The permission to check the permission on.
* @return whether {@code sender} has {@code perm}
*/
public boolean hasPermission(CommandSender sender, String perm) {
if (sender.isOp()) {
if (sender instanceof Player) {
if (this.getGlobalStateManager().get(((Player) sender).
getWorld()).opPermissions) {
return true;
}
} else {
return true;
}
}
// Invoke the permissions resolver
if (sender instanceof Player) {
Player player = (Player) sender;
return PermissionsResolverManager.getInstance().hasPermission(player.getWorld().getName(), player.getName(), perm);
}
return false;
}
/**
* Checks permissions and throws an exception if permission is not met.
*
* @param sender The sender to check the permission on.
* @param perm The permission to check the permission on.
* @throws CommandPermissionsException if {@code sender} doesn't have {@code perm}
*/
public void checkPermission(CommandSender sender, String perm)
throws CommandPermissionsException {
if (!hasPermission(sender, perm)) {
throw new CommandPermissionsException();
}
}
/**
* Checks to see if the sender is a player, otherwise throw an exception.
*
* @param sender The {@link CommandSender} to check
* @return {@code sender} casted to a player
* @throws CommandException if {@code sender} isn't a {@link Player}
*/
public Player checkPlayer(CommandSender sender)
throws CommandException {
if (sender instanceof Player) {
return (Player) sender;
} else {
throw new CommandException("A player is expected.");
}
}
/**
* Match player names.
*
* The filter string uses the following format:
* @[name] looks up all players with the exact {@code name}
* *[name] matches any player whose name contains {@code name}
* [name] matches any player whose name starts with {@code name}
*
* @param filter The filter string to check.
* @return A {@link List} of players who match {@code filter}
*/
public List<Player> matchPlayerNames(String filter) {
Player[] players = getServer().getOnlinePlayers();
filter = filter.toLowerCase();
// Allow exact name matching
if (filter.charAt(0) == '@' && filter.length() >= 2) {
filter = filter.substring(1);
for (Player player : players) {
if (player.getName().equalsIgnoreCase(filter)) {
List<Player> list = new ArrayList<Player>();
list.add(player);
return list;
}
}
return new ArrayList<Player>();
// Allow partial name matching
} else if (filter.charAt(0) == '*' && filter.length() >= 2) {
filter = filter.substring(1);
List<Player> list = new ArrayList<Player>();
for (Player player : players) {
if (player.getName().toLowerCase().contains(filter)) {
list.add(player);
}
}
return list;
// Start with name matching
} else {
List<Player> list = new ArrayList<Player>();
for (Player player : players) {
if (player.getName().toLowerCase().startsWith(filter)) {
list.add(player);
}
}
return list;
}
}
/**
* Checks if the given list of players is greater than size 0, otherwise
* throw an exception.
*
* @param players The {@link List} to check
* @return {@code players} as an {@link Iterable}
* @throws CommandException If {@code players} is empty
*/
protected Iterable<Player> checkPlayerMatch(List<Player> players)
throws CommandException {
// Check to see if there were any matches
if (players.size() == 0) {
throw new CommandException("No players matched query.");
}
return players;
}
/**
* Matches players based on the specified filter string
*
* The filter string format is as follows:
* * returns all the players currently online
* If {@code sender} is a {@link Player}:
* #world returns all players in the world that {@code sender} is in
* #near reaturns all players within 30 blocks of {@code sender}'s location
* Otherwise, the format is as specified in {@link #matchPlayerNames(String)}
*
* @param source The CommandSender who is trying to find a player
* @param filter The filter string for players
* @return iterator for players
* @throws CommandException if no matches are found
*/
public Iterable<Player> matchPlayers(CommandSender source, String filter)
throws CommandException {
if (getServer().getOnlinePlayers().length == 0) {
throw new CommandException("No players matched query.");
}
if (filter.equals("*")) {
return checkPlayerMatch(Arrays.asList(getServer().getOnlinePlayers()));
}
// Handle special hash tag groups
if (filter.charAt(0) == '#') {
// Handle #world, which matches player of the same world as the
// calling source
if (filter.equalsIgnoreCase("#world")) {
List<Player> players = new ArrayList<Player>();
Player sourcePlayer = checkPlayer(source);
World sourceWorld = sourcePlayer.getWorld();
for (Player player : getServer().getOnlinePlayers()) {
if (player.getWorld().equals(sourceWorld)) {
players.add(player);
}
}
return checkPlayerMatch(players);
// Handle #near, which is for nearby players.
} else if (filter.equalsIgnoreCase("#near")) {
List<Player> players = new ArrayList<Player>();
Player sourcePlayer = checkPlayer(source);
World sourceWorld = sourcePlayer.getWorld();
org.bukkit.util.Vector sourceVector
= sourcePlayer.getLocation().toVector();
for (Player player : getServer().getOnlinePlayers()) {
if (player.getWorld().equals(sourceWorld)
&& player.getLocation().toVector().distanceSquared(
sourceVector) < 900) {
players.add(player);
}
}
return checkPlayerMatch(players);
} else {
throw new CommandException("Invalid group '" + filter + "'.");
}
}
List<Player> players = matchPlayerNames(filter);
return checkPlayerMatch(players);
}
/**
* Match only a single player.
*
* @param sender The {@link CommandSender} who is requesting a player match
* @param filter The filter string.
* @see #matchPlayers(org.bukkit.entity.Player) for filter string syntax
* @return The single player
* @throws CommandException If more than one player match was found
*/
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();
Player match = players.next();
// We don't want to match the wrong person, so fail if if multiple
// players were found (we don't want to just pick off the first one,
// as that may be the wrong player)
if (players.hasNext()) {
throw new CommandException("More than one player found! " +
"Use @<name> for exact matching.");
}
return match;
}
/**
* Match only a single player or console.
*
* The filter string syntax is as follows:
* #console, *console, or ! return the server console
* All syntax from {@link #matchSinglePlayer(org.bukkit.command.CommandSender, String)}
* @param sender The sender trying to match a CommandSender
* @param filter The filter string
* @return The resulting CommandSender
* @throws CommandException if either zero or more than one player matched.
*/
public CommandSender matchPlayerOrConsole(CommandSender sender, String filter)
throws CommandException {
// Let's see if console is wanted
if (filter.equalsIgnoreCase("#console")
|| filter.equalsIgnoreCase("*console*")
|| filter.equalsIgnoreCase("!")) {
return getServer().getConsoleSender();
}
return matchSinglePlayer(sender, filter);
}
/**
* Get a single player as an iterator for players.
*
* @param player The player to return in an Iterable
* @return iterator for player
*/
public Iterable<Player> matchPlayers(Player player) {
return Arrays.asList(player);
}
/**
* Match a world.
*
* The filter string syntax is as follows:
* #main returns the main world
* #normal returns the first world with a normal environment
* #nether return the first world with a nether environment
* #player:[name] returns the world that a player named {@code name} is located in, if the player is online.
* [name] A world with the name {@code name}
*
* @param sender The sender requesting a match
* @param filter The filter string
* @return The resulting world
* @throws CommandException if no world matches
*/
public World matchWorld(CommandSender sender, String filter) throws CommandException {
List<World> worlds = getServer().getWorlds();
// Handle special hash tag groups
if (filter.charAt(0) == '#') {
// #main for the main world
if (filter.equalsIgnoreCase("#main")) {
return worlds.get(0);
// #normal for the first normal world
} else if (filter.equalsIgnoreCase("#normal")) {
for (World world : worlds) {
if (world.getEnvironment() == Environment.NORMAL) {
return world;
}
}
throw new CommandException("No normal world found.");
// #nether for the first nether world
} else if (filter.equalsIgnoreCase("#nether")) {
for (World world : worlds) {
if (world.getEnvironment() == Environment.NETHER) {
return world;
}
}
throw new CommandException("No nether world found.");
// Handle getting a world from a player
} else if (filter.matches("^#player$")) {
String parts[] = filter.split(":", 2);
// They didn't specify an argument for the player!
if (parts.length == 1) {
throw new CommandException("Argument expected for #player.");
}
return matchPlayers(sender, parts[1]).iterator().next().getWorld();
} else {
throw new CommandException("Invalid identifier '" + filter + "'.");
}
}
for (World world : worlds) {
if (world.getName().equals(filter)) {
return world;
}
}
throw new CommandException("No world by that exact name found.");
}
/**
* Gets a copy of the WorldEdit plugin.
*
* @return The WorldEditPlugin instance
* @throws CommandException If there is no WorldEditPlugin available
*/
public WorldEditPlugin getWorldEdit() throws CommandException {
Plugin worldEdit = getServer().getPluginManager().getPlugin("WorldEdit");
if (worldEdit == null) {
throw new CommandException("WorldEdit does not appear to be installed.");
}
if (worldEdit instanceof WorldEditPlugin) {
return (WorldEditPlugin) worldEdit;
} else {
throw new CommandException("WorldEdit detection failed (report error).");
}
}
/**
* Wrap a player as a LocalPlayer.
*
* @param player The player to wrap
* @return The wrapped player
*/
public LocalPlayer wrapPlayer(Player player) {
return new BukkitPlayer(this, player);
}
/**
* Create a default configuration file from the .jar.
*
* @param actual The destination file
* @param defaultName The name of the file inside the jar's defaults folder
*/
public void createDefaultConfiguration(File actual, String defaultName) {
// Make parent directories
File parent = actual.getParentFile();
if (!parent.exists()) {
parent.mkdirs();
}
if (actual.exists()) {
return;
}
InputStream input = WorldGuardPlugin.class.getResourceAsStream("/defaults/" + defaultName);
if (input == null) {
getLogger().severe("Unable to read default configuration: " + defaultName);
}
if (input != null) {
FileOutputStream output = null;
try {
output = new FileOutputStream(actual);
byte[] buf = new byte[8192];
int length = 0;
while ((length = input.read(buf)) > 0) {
output.write(buf, 0, length);
}
getLogger().info("Default configuration file written: "
+ actual.getAbsolutePath());
} catch (IOException e) {
e.printStackTrace();
} finally {
try {
if (input != null) {
input.close();
}
} catch (IOException ignore) {
}
try {
if (output != null) {
output.close();
}
} catch (IOException ignore) {
}
}
}
}
/**
* Notifies all with the worldguard.notify permission.
* This will check both superperms and WEPIF,
* but makes sure WEPIF checks don't result in duplicate notifications
*
* @param msg The notification to broadcast
*/
public void broadcastNotification(String msg) {
getServer().broadcast(msg, "worldguard.notify");
Set<Permissible> subs = getServer().getPluginManager().getPermissionSubscriptions("worldguard.notify");
for (Player player : getServer().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);
}
}
getLogger().info(msg);
}
/**
* Forgets a player.
*
* @param player The player to remove state information for
*/
public void forgetPlayer(Player player) {
}
/**
* Checks to see if a player can build at a location. This will return
* true if region protection is disabled.
*
* @param player The player to check.
* @param loc The location to check at.
* @see RegionManager#canBuild(org.bukkit.entity.Player, org.bukkit.Location)
* @return whether {@code player} can build at {@code loc}
*/
public boolean canBuild(Player player, Location loc) {
return getGlobalRegionManager().canBuild(player, loc);
}
/**
* Checks to see if a player can build at a location. This will return
* true if region protection is disabled.
*
* @param player The player to check
* @param block The block to check at.
* @see RegionManager#canBuild(org.bukkit.entity.Player, org.bukkit.block.Block)
* @return whether {@code player} can build at {@code block}'s location
*/
public boolean canBuild(Player player, Block block) {
return getGlobalRegionManager().canBuild(player, block);
}
/**
* Gets the region manager for a world.
*
* @param world world to get the region manager for
* @return the region manager or null if regions are not enabled
*/
public RegionIndex getRegionManager(World world) {
if (!getGlobalStateManager().get(world).useRegions) {
return null;
}
return getGlobalRegionManager().get(world);
}
/**
* Get the "lag stop mode" controller.
*
* @return the lag stop mode
*/
public LagStopMode getLagStopMode() {
return lagStopper;
}
/**
* Replace macros in the text.
*
* The macros replaced are as follows:
* %name%: The name of {@code sender}. See {@link #toName(org.bukkit.command.CommandSender)}
* %id%: The unique name of the sender. See {@link #toUniqueName(org.bukkit.command.CommandSender)}
* %online%: The number of players currently online on the server
* If {@code sender} is a Player:
* %world%: The name of the world {@code sender} is located in
* %health%: The health of {@code sender}. See {@link org.bukkit.entity.Player#getHealth()}
*
* @param sender The sender to check
* @param message The message to replace macros in
* @return The message with macros replaced
*/
public String replaceMacros(CommandSender sender, String message) {
Player[] online = getServer().getOnlinePlayers();
message = message.replace("%name%", toName(sender));
message = message.replace("%id%", toUniqueName(sender));
message = message.replace("%online%", String.valueOf(online.length));
if (sender instanceof Player) {
Player player = (Player) sender;
World world = player.getWorld();
message = message.replace("%world%", world.getName());
message = message.replace("%health%", String.valueOf(player.getHealth()));
}
return message;
}
}
@@ -0,0 +1,48 @@
package com.sk89q.worldguard.bukkit;
import org.bukkit.event.EventHandler;
import org.bukkit.event.Listener;
import org.bukkit.event.server.PluginDisableEvent;
import org.bukkit.event.server.PluginEnableEvent;
import org.bukkit.plugin.PluginManager;
/**
* Listener for server events.
*/
class WorldGuardServerListener implements Listener {
private final WorldGuardPlugin plugin;
/**
* Construct the listener.
*
* @param plugin WorldGuard plugin
*/
WorldGuardServerListener(WorldGuardPlugin plugin) {
this.plugin = plugin;
}
/**
* Register events.
*/
void registerEvents() {
PluginManager pm = plugin.getServer().getPluginManager();
pm.registerEvents(this, plugin);
}
@EventHandler
public void onPluginEnable(PluginEnableEvent event) {
// Legacy god mode
if (event.getPlugin().getDescription().getName().equalsIgnoreCase("CommandBook")) {
plugin.getGlobalStateManager().updateCommandBookGodMode();
}
}
@EventHandler
public void onPluginDisable(PluginDisableEvent event) {
// Legacy god mode
if (event.getPlugin().getDescription().getName().equalsIgnoreCase("CommandBook")) {
plugin.getGlobalStateManager().updateCommandBookGodMode();
}
}
}
@@ -0,0 +1,57 @@
// $Id$
/*
* Copyright (C) 2010 sk89q <http://www.sk89q.com>
* All rights reserved.
*/
package com.sk89q.worldguard.bukkit;
import org.bukkit.entity.Entity;
import org.bukkit.entity.Vehicle;
import org.bukkit.event.EventHandler;
import org.bukkit.event.Listener;
import org.bukkit.event.vehicle.VehicleDestroyEvent;
import com.sk89q.rulelists.DefaultAttachments;
import com.sk89q.rulelists.RuleSet;
/**
* Listener for vehicle events.
*/
class WorldGuardVehicleListener implements Listener {
private WorldGuardPlugin plugin;
/**
* Construct the listener.
*
* @param plugin WorldGuard plugin
*/
WorldGuardVehicleListener(WorldGuardPlugin plugin) {
this.plugin = plugin;
}
/**
* Register the events.
*/
void registerEvents() {
plugin.getServer().getPluginManager().registerEvents(this, plugin);
}
@EventHandler
public void onVehicleDestroy(VehicleDestroyEvent event) {
Vehicle vehicle = event.getVehicle();
Entity destroyer = event.getAttacker();
ConfigurationManager cfg = plugin.getGlobalStateManager();
WorldConfiguration wcfg = cfg.get(vehicle.getWorld());
// RuleLists
RuleSet rules = wcfg.getRuleList().get(DefaultAttachments.ENTITY_DAMAGE);
BukkitContext context = new BukkitContext(plugin, event);
context.setSourceEntity(destroyer);
context.setTargetEntity(vehicle);
if (rules.process(context)) {
event.setCancelled(true);
return;
}
}
}
@@ -0,0 +1,99 @@
// $Id$
/*
* WorldGuard
* Copyright (C) 2010 sk89q <http://www.sk89q.com>
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU 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 General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package com.sk89q.worldguard.bukkit;
import org.bukkit.Location;
import org.bukkit.event.EventHandler;
import org.bukkit.event.EventPriority;
import org.bukkit.event.Listener;
import org.bukkit.event.weather.LightningStrikeEvent;
import org.bukkit.event.weather.ThunderChangeEvent;
import org.bukkit.event.weather.WeatherChangeEvent;
import com.sk89q.rulelists.DefaultAttachments;
import com.sk89q.rulelists.RuleSet;
/**
* Listener for weather events.
*/
class WorldGuardWeatherListener implements Listener {
private WorldGuardPlugin plugin;
/**
* Construct the listener.
*
* @param plugin WorldGuard plugin
*/
WorldGuardWeatherListener(WorldGuardPlugin plugin) {
this.plugin = plugin;
}
/**
* Register the events.
*/
void registerEvents() {
plugin.getServer().getPluginManager().registerEvents(this, plugin);
}
@EventHandler(priority = EventPriority.HIGH, ignoreCancelled = true)
public void onWeatherChange(WeatherChangeEvent event) {
ConfigurationManager cfg = plugin.getGlobalStateManager();
WorldConfiguration wcfg = cfg.get(event.getWorld());
// RuleLists
RuleSet rules = wcfg.getRuleList().get(DefaultAttachments.WEATHER_TRANSITION);
BukkitContext context = new BukkitContext(plugin, event);
if (rules.process(context)) {
event.setCancelled(true);
return;
}
}
@EventHandler(priority = EventPriority.HIGH, ignoreCancelled = true)
public void onThunderChange(ThunderChangeEvent event) {
ConfigurationManager cfg = plugin.getGlobalStateManager();
WorldConfiguration wcfg = cfg.get(event.getWorld());
// RuleLists
RuleSet rules = wcfg.getRuleList().get(DefaultAttachments.WEATHER_TRANSITION);
BukkitContext context = new BukkitContext(plugin, event);
if (rules.process(context)) {
event.setCancelled(true);
return;
}
}
@EventHandler(priority = EventPriority.HIGH, ignoreCancelled = true)
public void onLightningStrike(LightningStrikeEvent event) {
Location loc = event.getLightning().getLocation();
ConfigurationManager cfg = plugin.getGlobalStateManager();
WorldConfiguration wcfg = cfg.get(event.getWorld());
// RuleLists
RuleSet rules = wcfg.getRuleList().get(DefaultAttachments.WEATHER_PHENOMENON);
BukkitContext context = new BukkitContext(plugin, event);
context.setTargetBlock(loc.getBlock().getState());
if (rules.process(context)) {
event.setCancelled(true);
return;
}
}
}
@@ -0,0 +1,79 @@
// $Id$
/*
* Copyright (C) 2010 sk89q <http://www.sk89q.com>
* All rights reserved.
*/
package com.sk89q.worldguard.bukkit;
import org.bukkit.event.EventHandler;
import org.bukkit.event.Listener;
import org.bukkit.event.world.WorldLoadEvent;
import org.bukkit.event.world.WorldSaveEvent;
import org.bukkit.event.world.WorldUnloadEvent;
import com.sk89q.rulelists.DefaultAttachments;
import com.sk89q.rulelists.RuleSet;
/**
* Listener for world events.
*/
public class WorldGuardWorldListener implements Listener {
private WorldGuardPlugin plugin;
/**
* Construct the listener.
*
* @param plugin WorldGuard plugin
*/
public WorldGuardWorldListener(WorldGuardPlugin plugin) {
this.plugin = plugin;
}
/**
* Register the events.
*/
public void registerEvents() {
plugin.getServer().getPluginManager().registerEvents(this, plugin);
}
@EventHandler
public void onWorldLoad(WorldLoadEvent event) {
ConfigurationManager cfg = plugin.getGlobalStateManager();
WorldConfiguration wcfg = cfg.get(event.getWorld());
/* --- No short-circuit returns below this line --- */
// RuleLists
RuleSet rules = wcfg.getRuleList().get(DefaultAttachments.WORLD_LOAD);
BukkitContext context = new BukkitContext(plugin, event);
rules.process(context);
}
@EventHandler
public void onWorldLoad(WorldUnloadEvent event) {
ConfigurationManager cfg = plugin.getGlobalStateManager();
WorldConfiguration wcfg = cfg.get(event.getWorld());
// RuleLists
RuleSet rules = wcfg.getRuleList().get(DefaultAttachments.WORLD_UNLOAD);
BukkitContext context = new BukkitContext(plugin, event);
if (rules.process(context)) {
event.setCancelled(true);
return;
}
}
@EventHandler
public void onWorldSave(WorldSaveEvent event) {
ConfigurationManager cfg = plugin.getGlobalStateManager();
WorldConfiguration wcfg = cfg.get(event.getWorld());
/* --- No short-circuit returns below this line --- */
// RuleLists
RuleSet rules = wcfg.getRuleList().get(DefaultAttachments.WORLD_SAVE);
BukkitContext context = new BukkitContext(plugin, event);
rules.process(context);
}
}
@@ -0,0 +1,303 @@
// $Id$
/*
* WorldGuard
* Copyright (C) 2010 sk89q <http://www.sk89q.com>
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU 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 General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
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;
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;
public class GeneralCommands {
private final WorldGuardPlugin plugin;
public GeneralCommands(WorldGuardPlugin plugin) {
this.plugin = plugin;
}
@SuppressWarnings("deprecation")
@Command(aliases = {"god"}, usage = "[player]",
desc = "Enable godmode on a player", flags = "s", max = 1)
public void god(CommandContext args, CommandSender sender) throws CommandException {
ConfigurationManager config = plugin.getGlobalStateManager();
Iterable<Player> targets = null;
boolean included = false;
// Detect arguments based on the number of arguments provided
if (args.argsLength() == 0) {
targets = plugin.matchPlayers(plugin.checkPlayer(sender));
// Check permissions!
plugin.checkPermission(sender, "worldguard.god");
} else if (args.argsLength() == 1) {
targets = plugin.matchPlayers(sender, args.getString(0));
// Check permissions!
plugin.checkPermission(sender, "worldguard.god.other");
}
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) + ".");
}
}
// 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.");
}
}
@SuppressWarnings("deprecation")
@Command(aliases = {"ungod"}, usage = "[player]",
desc = "Disable godmode on a player", flags = "s", max = 1)
public void ungod(CommandContext args, CommandSender sender) throws CommandException {
ConfigurationManager config = plugin.getGlobalStateManager();
Iterable<Player> targets = null;
boolean included = false;
// Detect arguments based on the number of arguments provided
if (args.argsLength() == 0) {
targets = plugin.matchPlayers(plugin.checkPlayer(sender));
// Check permissions!
plugin.checkPermission(sender, "worldguard.god");
} else if (args.argsLength() == 1) {
targets = plugin.matchPlayers(sender, args.getString(0));
// Check permissions!
plugin.checkPermission(sender, "worldguard.god.other");
}
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) + ".");
}
}
// 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.");
}
}
@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;
boolean included = false;
// Detect arguments based on the number of arguments provided
if (args.argsLength() == 0) {
targets = plugin.matchPlayers(plugin.checkPlayer(sender));
// Check permissions!
plugin.checkPermission(sender, "worldguard.heal");
} else if (args.argsLength() == 1) {
targets = plugin.matchPlayers(sender, args.getString(0));
// Check permissions!
plugin.checkPermission(sender, "worldguard.heal.other");
}
for (Player player : targets) {
player.setHealth(20);
player.setFoodLevel(20);
// Tell the user
if (player.equals(sender)) {
player.sendMessage(ChatColor.YELLOW + "Healed!");
// Keep track of this
included = true;
} else {
player.sendMessage(ChatColor.YELLOW + "Healed 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 healed.");
}
}
@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;
boolean included = false;
// Detect arguments based on the number of arguments provided
if (args.argsLength() == 0) {
targets = plugin.matchPlayers(plugin.checkPlayer(sender));
// Check permissions!
plugin.checkPermission(sender, "worldguard.slay");
} else if (args.argsLength() == 1) {
targets = plugin.matchPlayers(sender, args.getString(0));
// Check permissions!
plugin.checkPermission(sender, "worldguard.slay.other");
}
for (Player player : targets) {
player.setHealth(0);
// Tell the user
if (player.equals(sender)) {
player.sendMessage(ChatColor.YELLOW + "Slain!");
// Keep track of this
included = true;
} else {
player.sendMessage(ChatColor.YELLOW + "Slain 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 slain.");
}
}
@Command(aliases = {"locate"}, usage = "[player]", desc = "Locate a player", max = 1)
@CommandPermissions({"worldguard.locate"})
public void locate(CommandContext args, CommandSender sender) throws CommandException {
Player player = plugin.checkPlayer(sender);
if (args.argsLength() == 0) {
player.setCompassTarget(player.getWorld().getSpawnLocation());
sender.sendMessage(ChatColor.YELLOW.toString() + "Compass reset to spawn.");
} else {
Player target = plugin.matchSinglePlayer(sender, args.getString(0));
player.setCompassTarget(target.getLocation());
sender.sendMessage(ChatColor.YELLOW.toString() + "Compass repointed.");
}
}
@Command(aliases = {"stack", ";"}, usage = "", desc = "Stack items", max = 0)
@CommandPermissions({"worldguard.stack"})
public void stack(CommandContext args, CommandSender sender) throws CommandException {
Player player = plugin.checkPlayer(sender);
boolean ignoreMax = plugin.hasPermission(player, "worldguard.stack.illegitimate");
boolean ignoreDamaged = plugin.hasPermission(player, "worldguard.stack.damaged");
ItemStack[] items = player.getInventory().getContents();
int len = items.length;
int affected = 0;
for (int i = 0; i < len; i++) {
ItemStack item = items[i];
// Avoid infinite stacks and stacks with durability
if (item == null || item.getAmount() <= 0
|| (!ignoreMax && item.getMaxStackSize() == 1)) {
continue;
}
int max = ignoreMax ? 64 : item.getMaxStackSize();
if (item.getAmount() < max) {
int needed = max - item.getAmount(); // Number of needed items until max
// Find another stack of the same type
for (int j = i + 1; j < len; j++) {
ItemStack item2 = items[j];
// Avoid infinite stacks and stacks with durability
if (item2 == null || item2.getAmount() <= 0
|| (!ignoreMax && item.getMaxStackSize() == 1)) {
continue;
}
// Same type?
// Blocks store their color in the damage value
if (item2.getTypeId() == item.getTypeId() &&
((!ItemType.usesDamageValue(item.getTypeId()) && ignoreDamaged)
|| item.getDurability() == item2.getDurability()) &&
item.getEnchantments().equals(item2.getEnchantments())) {
// This stack won't fit in the parent stack
if (item2.getAmount() > needed) {
item.setAmount(max);
item2.setAmount(item2.getAmount() - needed);
break;
// This stack will
} else {
items[j] = null;
item.setAmount(item.getAmount() + item2.getAmount());
needed = max - item.getAmount();
}
affected++;
}
}
}
}
if (affected > 0) {
player.getInventory().setContents(items);
}
player.sendMessage(ChatColor.YELLOW + "Items compacted into stacks!");
}
}
@@ -0,0 +1,44 @@
// $Id$
/*
* WorldGuard
* Copyright (C) 2010 sk89q <http://www.sk89q.com>
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU 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 General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package com.sk89q.worldguard.bukkit.commands;
import org.bukkit.command.CommandSender;
import com.sk89q.minecraft.util.commands.Command;
import com.sk89q.minecraft.util.commands.CommandContext;
import com.sk89q.minecraft.util.commands.NestedCommand;
import com.sk89q.worldguard.bukkit.WorldGuardPlugin;
public class ProtectionCommands {
@SuppressWarnings("unused")
private final WorldGuardPlugin plugin;
public ProtectionCommands(WorldGuardPlugin plugin) {
this.plugin = plugin;
}
@Command(aliases = {"region", "regions", "rg"}, desc = "Region management commands")
@NestedCommand({RegionCommands.class, RegionMemberCommands.class})
public void region(CommandContext args, CommandSender sender) {}
@Command(aliases = {"worldguard", "wg"}, desc = "WorldGuard commands")
@NestedCommand({WorldGuardCommands.class})
public void worldGuard(CommandContext args, CommandSender sender) {}
}
@@ -0,0 +1,965 @@
// $Id$
/*
* WorldGuard
* Copyright (C) 2010 sk89q <http://www.sk89q.com>
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU 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 General Public License for more details.
*
* You should have received a copy of the GNU 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.worldedit.BlockVector;
import com.sk89q.worldedit.Location;
import com.sk89q.worldedit.Vector;
import com.sk89q.worldedit.bukkit.BukkitUtil;
import com.sk89q.worldedit.bukkit.WorldEditPlugin;
import com.sk89q.worldedit.bukkit.selections.CuboidSelection;
import com.sk89q.worldedit.bukkit.selections.Polygonal2DSelection;
import com.sk89q.worldedit.bukkit.selections.Selection;
import com.sk89q.worldguard.LocalPlayer;
import com.sk89q.worldguard.bukkit.WorldConfiguration;
import com.sk89q.worldguard.bukkit.WorldGuardPlugin;
import com.sk89q.worldguard.region.ApplicableRegionSet;
import com.sk89q.worldguard.region.Region;
import com.sk89q.worldguard.region.flags.*;
import com.sk89q.worldguard.region.indices.RegionIndex;
import com.sk89q.worldguard.region.shapes.Cuboid;
import com.sk89q.worldguard.region.shapes.ExtrudedPolygon;
import org.bukkit.ChatColor;
import org.bukkit.World;
import org.bukkit.command.CommandSender;
import org.bukkit.entity.Player;
import java.lang.reflect.InvocationTargetException;
import java.util.*;
public class RegionCommands {
private final WorldGuardPlugin plugin;
private MigratorKey migrateDBRequest;
private Date migrateDBRequestDate;
public RegionCommands(WorldGuardPlugin plugin) {
this.plugin = plugin;
}
@Command(aliases = {"define", "def", "d"}, usage = "<id> [<owner1> [<owner2> [<owners...>]]]",
desc = "Defines a region", min = 1)
@CommandPermissions({"worldguard.region.define"})
public void define(CommandContext args, CommandSender sender) throws CommandException {
Player player = plugin.checkPlayer(sender);
WorldEditPlugin worldEdit = plugin.getWorldEdit();
String id = args.getString(0);
if (!Region.isValidId(id)) {
throw new CommandException("Invalid region ID specified!");
}
if (id.equalsIgnoreCase("__global__")) {
throw new CommandException("A region cannot be named __global__");
}
// Attempt to get the player's selection from WorldEdit
Selection sel = worldEdit.getSelection(player);
if (sel == null) {
throw new CommandException("Select a region with WorldEdit first.");
}
RegionIndex mgr = plugin.getGlobalRegionManager().get(sel.getWorld());
if (mgr.hasRegion(id)) {
throw new CommandException("That region is already defined. Use redefine instead.");
}
Region region;
// Detect the type of region from WorldEdit
if (sel instanceof Polygonal2DSelection) {
Polygonal2DSelection polySel = (Polygonal2DSelection) sel;
int minY = polySel.getNativeMinimumPoint().getBlockY();
int maxY = polySel.getNativeMaximumPoint().getBlockY();
region = new ExtrudedPolygon(id, polySel.getNativePoints(), minY, maxY);
} else if (sel instanceof CuboidSelection) {
BlockVector min = sel.getNativeMinimumPoint().toBlockVector();
BlockVector max = sel.getNativeMaximumPoint().toBlockVector();
region = new Cuboid(id, min, max);
} else {
throw new CommandException(
"The type of region selected in WorldEdit is unsupported in WorldGuard!");
}
// Get the list of region owners
if (args.argsLength() > 1) {
region.setOwners(RegionDBUtil.parseDomainString(args.getSlice(1), 1));
}
mgr.addRegion(region);
try {
mgr.save();
sender.sendMessage(ChatColor.YELLOW + "Region saved as " + id + ".");
} catch (ProtectionDatabaseException e) {
throw new CommandException("Failed to write regions: "
+ e.getMessage());
}
}
@Command(aliases = {"redefine", "update", "move"}, usage = "<id>",
desc = "Re-defines the shape of a region", min = 1, max = 1)
public void redefine(CommandContext args, CommandSender sender) throws CommandException {
Player player = plugin.checkPlayer(sender);
World world = player.getWorld();
WorldEditPlugin worldEdit = plugin.getWorldEdit();
LocalPlayer localPlayer = plugin.wrapPlayer(player);
String id = args.getString(0);
if (id.equalsIgnoreCase("__global__")) {
throw new CommandException("The region cannot be named __global__");
}
RegionIndex mgr = plugin.getGlobalRegionManager().get(world);
Region existing = mgr.getRegionExact(id);
if (existing == null) {
throw new CommandException("Could not find a region by that ID.");
}
if (existing.isOwner(localPlayer)) {
plugin.checkPermission(sender, "worldguard.region.redefine.own");
} else if (existing.isMember(localPlayer)) {
plugin.checkPermission(sender, "worldguard.region.redefine.member");
} else {
plugin.checkPermission(sender, "worldguard.region.redefine");
}
// Attempt to get the player's selection from WorldEdit
Selection sel = worldEdit.getSelection(player);
if (sel == null) {
throw new CommandException("Select a region with WorldEdit first.");
}
Region region;
// Detect the type of region from WorldEdit
if (sel instanceof Polygonal2DSelection) {
Polygonal2DSelection polySel = (Polygonal2DSelection) sel;
int minY = polySel.getNativeMinimumPoint().getBlockY();
int maxY = polySel.getNativeMaximumPoint().getBlockY();
region = new ExtrudedPolygon(id, polySel.getNativePoints(), minY, maxY);
} else if (sel instanceof CuboidSelection) {
BlockVector min = sel.getNativeMinimumPoint().toBlockVector();
BlockVector max = sel.getNativeMaximumPoint().toBlockVector();
region = new Cuboid(id, min, max);
} else {
throw new CommandException(
"The type of region selected in WorldEdit is unsupported in WorldGuard!");
}
region.setMembers(existing.getMembers());
region.setOwners(existing.getOwners());
region.setFlags(existing.getFlags());
region.setPriority(existing.getPriority());
try {
region.setParent(existing.getParent());
} catch (CircularInheritanceException ignore) {
}
mgr.addRegion(region);
sender.sendMessage(ChatColor.YELLOW + "Region updated with new area.");
try {
mgr.save();
} catch (ProtectionDatabaseException e) {
throw new CommandException("Failed to write regions: "
+ e.getMessage());
}
}
@Command(aliases = {"select", "sel", "s"}, usage = "[id]",
desc = "Load a region as a WorldEdit selection", min = 0, max = 1)
public void select(CommandContext args, CommandSender sender) throws CommandException {
final Player player = plugin.checkPlayer(sender);
final World world = player.getWorld();
final LocalPlayer localPlayer = plugin.wrapPlayer(player);
final RegionIndex mgr = plugin.getGlobalRegionManager().get(world);
final String id;
if (args.argsLength() == 0) {
final Vector pt = localPlayer.getPosition();
final ApplicableRegionSet set = mgr.getApplicableRegions(pt);
if (set.size() == 0) {
throw new CommandException("No region ID specified and no region found at current location!");
}
id = set.iterator().next().getId();
}
else {
id = args.getString(0);
}
final Region region = mgr.getRegion(id);
if (region == null) {
throw new CommandException("Could not find a region by that ID.");
}
selectRegion(player, localPlayer, region);
}
public void selectRegion(Player player, LocalPlayer localPlayer, Region region) throws CommandException, CommandPermissionsException {
final WorldEditPlugin worldEdit = plugin.getWorldEdit();
final String id = region.getId();
if (region.isOwner(localPlayer)) {
plugin.checkPermission(player, "worldguard.region.select.own." + id.toLowerCase());
} else if (region.isMember(localPlayer)) {
plugin.checkPermission(player, "worldguard.region.select.member." + id.toLowerCase());
} else {
plugin.checkPermission(player, "worldguard.region.select." + id.toLowerCase());
}
final World world = player.getWorld();
if (region instanceof Cuboid) {
final Cuboid cuboid = (Cuboid) region;
final Vector pt1 = cuboid.getAABBMin();
final Vector pt2 = cuboid.getAABBMax();
final CuboidSelection selection = new CuboidSelection(world, pt1, pt2);
worldEdit.setSelection(player, selection);
player.sendMessage(ChatColor.YELLOW + "Region selected as a cuboid.");
} else if (region instanceof ExtrudedPolygon) {
final ExtrudedPolygon poly2d = (ExtrudedPolygon) region;
final Polygonal2DSelection selection = new Polygonal2DSelection(
world, poly2d.getPoints(),
poly2d.getAABBMin().getBlockY(),
poly2d.getAABBMax().getBlockY()
);
worldEdit.setSelection(player, selection);
player.sendMessage(ChatColor.YELLOW + "Region selected as a polygon.");
} else if (region instanceof GlobalProtectedRegion) {
throw new CommandException("Can't select global regions.");
} else {
throw new CommandException("Unknown region type: " + region.getClass().getCanonicalName());
}
}
@Command(aliases = {"info", "i"}, usage = "[world] [id]", flags = "s",
desc = "Get information about a region", min = 0, max = 2)
public void info(CommandContext args, CommandSender sender) throws CommandException {
final LocalPlayer localPlayer;
final World world;
if (sender instanceof Player) {
final Player player = (Player) sender;
localPlayer = plugin.wrapPlayer(player);
world = player.getWorld();
} else if (args.argsLength() < 2) {
throw new CommandException("A player is expected.");
} else {
localPlayer = null;
world = plugin.matchWorld(sender, args.getString(0));
}
final RegionIndex mgr = plugin.getGlobalRegionManager().get(world);
final String id;
// Get different values based on provided arguments
switch (args.argsLength()) {
case 0:
if (localPlayer == null) {
throw new CommandException("A player is expected.");
}
final Vector pt = localPlayer.getPosition();
final ApplicableRegionSet set = mgr.getApplicableRegions(pt);
if (set.size() == 0) {
throw new CommandException("No region ID specified and no region found at current location!");
}
id = set.iterator().next().getId();
break;
case 1:
id = args.getString(0).toLowerCase();
break;
default:
id = args.getString(1).toLowerCase();
}
final Region region = mgr.getRegion(id);
if (region == null) {
if (!Region.isValidId(id)) {
throw new CommandException("Invalid region ID specified!");
}
throw new CommandException("A region with ID '" + id + "' doesn't exist.");
}
displayRegionInfo(sender, localPlayer, region);
if (args.hasFlag('s')) {
selectRegion(plugin.checkPlayer(sender), localPlayer, region);
}
}
public void displayRegionInfo(CommandSender sender, final LocalPlayer localPlayer, Region region) throws CommandPermissionsException {
if (localPlayer == null) {
plugin.checkPermission(sender, "worldguard.region.info");
} else if (region.isOwner(localPlayer)) {
plugin.checkPermission(sender, "worldguard.region.info.own");
} else if (region.isMember(localPlayer)) {
plugin.checkPermission(sender, "worldguard.region.info.member");
} else {
plugin.checkPermission(sender, "worldguard.region.info");
}
final String id = region.getId();
sender.sendMessage(ChatColor.YELLOW + "Region: " + id + ChatColor.GRAY + ", type: " + region.getTypeName() + ", " + ChatColor.BLUE + "Priority: " + region.getPriority());
boolean hasFlags = false;
final StringBuilder s = new StringBuilder(ChatColor.BLUE + "Flags: ");
for (Flag<?> flag : DefaultFlag.getFlags()) {
Object val = region.getFlag(flag), group = null;
if (val == null) {
continue;
}
if (hasFlags) {
s.append(", ");
}
RegionGroupFlag groupFlag = flag.getRegionGroupFlag();
if (groupFlag != null) {
group = region.getFlag(groupFlag);
}
if(group == null) {
s.append(flag.getName()).append(": ").append(String.valueOf(val));
} else {
s.append(flag.getName()).append(" -g ").append(String.valueOf(group)).append(": ").append(String.valueOf(val));
}
hasFlags = true;
}
if (hasFlags) {
sender.sendMessage(s.toString());
}
if (region.getParent() != null) {
sender.sendMessage(ChatColor.BLUE + "Parent: " + region.getParent().getId());
}
final DefaultDomain owners = region.getOwners();
if (owners.size() != 0) {
sender.sendMessage(ChatColor.LIGHT_PURPLE + "Owners: " + owners.toUserFriendlyString());
}
final DefaultDomain members = region.getMembers();
if (members.size() != 0) {
sender.sendMessage(ChatColor.LIGHT_PURPLE + "Members: " + members.toUserFriendlyString());
}
final BlockVector min = region.getAABBMin();
final BlockVector max = region.getAABBMax();
sender.sendMessage(ChatColor.LIGHT_PURPLE + "Bounds:"
+ " (" + min.getBlockX() + "," + min.getBlockY() + "," + min.getBlockZ() + ")"
+ " (" + max.getBlockX() + "," + max.getBlockY() + "," + max.getBlockZ() + ")"
);
}
public class RegionEntry implements Comparable<RegionEntry>{
private final String id;
private final int index;
private boolean isOwner;
private boolean isMember;
public RegionEntry(String id, int index) {
this.id = id;
this.index = index;
}
@Override
public int compareTo(RegionEntry o) {
if (isOwner != o.isOwner) {
return isOwner ? 1 : -1;
}
if (isMember != o.isMember) {
return isMember ? 1 : -1;
}
return id.compareTo(o.id);
}
@Override
public String toString() {
if (isOwner) {
return (index + 1) + ". +" + id;
} else if (isMember) {
return (index + 1) + ". -" + id;
} else {
return (index + 1) + ". " + id;
}
}
}
@Command(aliases = {"list"}, usage = "[.player] [page] [world]",
desc = "Get a list of regions", max = 3)
//@CommandPermissions({"worldguard.region.list"})
public void list(CommandContext args, CommandSender sender) throws CommandException {
World world;
int page = 0;
int argOffset = 0;
String name = "";
boolean own = false;
LocalPlayer localPlayer = null;
final String senderName = sender.getName().toLowerCase();
if (args.argsLength() > 0 && args.getString(0).startsWith(".")) {
name = args.getString(0).substring(1).toLowerCase();
argOffset = 1;
if (name.equals("me") || name.isEmpty() || name.equals(senderName)) {
own = true;
}
}
// Make /rg list default to "own" mode if the "worldguard.region.list" permission is not given
if (!own && !plugin.hasPermission(sender, "worldguard.region.list")) {
own = true;
}
if (own) {
plugin.checkPermission(sender, "worldguard.region.list.own");
name = senderName;
localPlayer = plugin.wrapPlayer(plugin.checkPlayer(sender));
}
if (args.argsLength() > argOffset) {
page = Math.max(0, args.getInteger(argOffset) - 1);
}
if (args.argsLength() > 1 + argOffset) {
world = plugin.matchWorld(sender, args.getString(1 + argOffset));
} else {
world = plugin.checkPlayer(sender).getWorld();
}
final RegionIndex mgr = plugin.getGlobalRegionManager().get(world);
final Map<String, Region> regions = mgr.getRegions();
List<RegionEntry> regionEntries = new ArrayList<RegionEntry>();
int index = 0;
for (String id : regions.keySet()) {
RegionEntry entry = new RegionEntry(id, index++);
if (!name.isEmpty()) {
if (own) {
entry.isOwner = regions.get(id).isOwner(localPlayer);
entry.isMember = regions.get(id).isMember(localPlayer);
}
else {
entry.isOwner = regions.get(id).isOwner(name);
entry.isMember = regions.get(id).isMember(name);
}
if (!entry.isOwner && !entry.isMember) {
continue;
}
}
regionEntries.add(entry);
}
Collections.sort(regionEntries);
final int totalSize = regionEntries.size();
final int pageSize = 10;
final int pages = (int) Math.ceil(totalSize / (float) pageSize);
sender.sendMessage(ChatColor.RED
+ (name.equals("") ? "Regions (page " : "Regions for " + name + " (page ")
+ (page + 1) + " of " + pages + "):");
if (page < pages) {
for (int i = page * pageSize; i < page * pageSize + pageSize; i++) {
if (i >= totalSize) {
break;
}
sender.sendMessage(ChatColor.YELLOW.toString() + regionEntries.get(i));
}
}
}
@Command(aliases = {"flag", "f"}, usage = "<id> <flag> [-g group] [value]", flags = "g:",
desc = "Set flags", min = 2)
public void flag(CommandContext args, CommandSender sender) throws CommandException {
Player player = plugin.checkPlayer(sender);
World world = player.getWorld();
LocalPlayer localPlayer = plugin.wrapPlayer(player);
String id = args.getString(0);
String flagName = args.getString(1);
String value = null;
RegionGroup groupValue = null;
if (args.argsLength() >= 3) {
value = args.getJoinedStrings(2);
}
RegionIndex mgr = plugin.getGlobalRegionManager().get(world);
Region region = mgr.getRegion(id);
if (region == null) {
if (id.equalsIgnoreCase("__global__")) {
region = new GlobalProtectedRegion(id);
mgr.addRegion(region);
} else {
throw new CommandException("Could not find a region by that ID.");
}
}
// @TODO deprecate "flag.[own./member./blank]"
boolean hasPerm = false;
if (region.isOwner(localPlayer)) {
if (plugin.hasPermission(sender, "worldguard.region.flag.own." + id.toLowerCase())) hasPerm = true;
else if (plugin.hasPermission(sender, "worldguard.region.flag.regions.own." + id.toLowerCase())) hasPerm = true;
} else if (region.isMember(localPlayer)) {
if (plugin.hasPermission(sender, "worldguard.region.flag.member." + id.toLowerCase())) hasPerm = true;
else if (plugin.hasPermission(sender, "worldguard.region.flag.regions.member." + id.toLowerCase())) hasPerm = true;
} else {
if (plugin.hasPermission(sender, "worldguard.region.flag." + id.toLowerCase())) hasPerm = true;
else if (plugin.hasPermission(sender, "worldguard.region.flag.regions." + id.toLowerCase())) hasPerm = true;
}
if (!hasPerm) throw new CommandPermissionsException();
Flag<?> foundFlag = null;
// Now time to find the flag!
for (Flag<?> flag : DefaultFlag.getFlags()) {
// Try to detect the flag
if (flag.getName().replace("-", "").equalsIgnoreCase(flagName.replace("-", ""))) {
foundFlag = flag;
break;
}
}
if (foundFlag == null) {
StringBuilder list = new StringBuilder();
// Need to build a list
for (Flag<?> flag : DefaultFlag.getFlags()) {
if (list.length() > 0) {
list.append(", ");
}
// @TODO deprecate inconsistant "owner" permission
if (region.isOwner(localPlayer)) {
if (!plugin.hasPermission(sender, "worldguard.region.flag.flags."
+ flag.getName() + ".owner." + id.toLowerCase())
&& !plugin.hasPermission(sender, "worldguard.region.flag.flags."
+ flag.getName() + ".own." + id.toLowerCase())) {
continue;
}
} else if (region.isMember(localPlayer)) {
if (!plugin.hasPermission(sender, "worldguard.region.flag.flags."
+ flag.getName() + ".member." + id.toLowerCase())) {
continue;
}
} else {
if (!plugin.hasPermission(sender, "worldguard.region.flag.flags."
+ flag.getName() + "." + id.toLowerCase())) {
continue;
}
}
list.append(flag.getName());
}
player.sendMessage(ChatColor.RED + "Unknown flag specified: " + flagName);
player.sendMessage(ChatColor.RED + "Available flags: " + list);
return;
}
if (region.isOwner(localPlayer)) {
plugin.checkPermission(sender, "worldguard.region.flag.flags."
+ foundFlag.getName() + ".owner." + id.toLowerCase());
} else if (region.isMember(localPlayer)) {
plugin.checkPermission(sender, "worldguard.region.flag.flags."
+ foundFlag.getName() + ".member." + id.toLowerCase());
} else {
plugin.checkPermission(sender, "worldguard.region.flag.flags."
+ foundFlag.getName() + "." + id.toLowerCase());
}
if (args.hasFlag('g')) {
String group = args.getFlag('g');
RegionGroupFlag groupFlag = foundFlag.getRegionGroupFlag();
if (groupFlag == null) {
throw new CommandException("Region flag '" + foundFlag.getName()
+ "' does not have a group flag!");
}
// Parse the [-g group] separately so entire command can abort if parsing
// the [value] part throws an error.
try {
groupValue = groupFlag.parseInput(plugin, sender, group);
} catch (InvalidFlagFormat e) {
throw new CommandException(e.getMessage());
}
}
if (value != null) {
// Set the flag if [value] was given even if [-g group] was given as well
try {
setFlag(region, foundFlag, sender, value);
} catch (InvalidFlagFormat e) {
throw new CommandException(e.getMessage());
}
sender.sendMessage(ChatColor.YELLOW
+ "Region flag '" + foundFlag.getName() + "' set.");
}
if (value == null && !args.hasFlag('g')) {
// Clear the flag only if neither [value] nor [-g group] was given
region.setFlag(foundFlag, null);
// Also clear the associated group flag if one exists
RegionGroupFlag groupFlag = foundFlag.getRegionGroupFlag();
if (groupFlag != null) {
region.setFlag(groupFlag, null);
}
sender.sendMessage(ChatColor.YELLOW
+ "Region flag '" + foundFlag.getName() + "' cleared.");
}
if (groupValue != null) {
RegionGroupFlag groupFlag = foundFlag.getRegionGroupFlag();
// If group set to the default, then clear the group flag
if (groupValue == groupFlag.getDefault()) {
region.setFlag(groupFlag, null);
sender.sendMessage(ChatColor.YELLOW
+ "Region group flag for '" + foundFlag.getName() + "' reset to default.");
} else {
region.setFlag(groupFlag, groupValue);
sender.sendMessage(ChatColor.YELLOW
+ "Region group flag for '" + foundFlag.getName() + "' set.");
}
}
try {
mgr.save();
} catch (ProtectionDatabaseException e) {
throw new CommandException("Failed to write regions: "
+ e.getMessage());
}
}
public <V> void setFlag(Region region,
Flag<V> flag, CommandSender sender, String value)
throws InvalidFlagFormat {
region.setFlag(flag, flag.parseInput(plugin, sender, value));
}
@Command(aliases = {"setpriority", "priority", "pri"}, usage = "<id> <priority>",
desc = "Set the priority of a region", min = 2, max = 2)
public void setPriority(CommandContext args, CommandSender sender) throws CommandException {
Player player = plugin.checkPlayer(sender);
World world = player.getWorld();
LocalPlayer localPlayer = plugin.wrapPlayer(player);
String id = args.getString(0);
int priority = args.getInteger(1);
if (id.equalsIgnoreCase("__global__")) {
throw new CommandException("The region cannot be named __global__");
}
RegionIndex mgr = plugin.getGlobalRegionManager().get(world);
Region region = mgr.getRegion(id);
if (region == null) {
throw new CommandException("Could not find a region by that ID.");
}
id = region.getId();
if (region.isOwner(localPlayer)) {
plugin.checkPermission(sender, "worldguard.region.setpriority.own." + id.toLowerCase());
} else if (region.isMember(localPlayer)) {
plugin.checkPermission(sender, "worldguard.region.setpriority.member." + id.toLowerCase());
} else {
plugin.checkPermission(sender, "worldguard.region.setpriority." + id.toLowerCase());
}
region.setPriority(priority);
sender.sendMessage(ChatColor.YELLOW
+ "Priority of '" + region.getId() + "' set to "
+ priority + ".");
try {
mgr.save();
} catch (ProtectionDatabaseException e) {
throw new CommandException("Failed to write regions: "
+ e.getMessage());
}
}
@Command(aliases = {"setparent", "parent", "par"}, usage = "<id> [parent-id]",
desc = "Set the parent of a region", min = 1, max = 2)
public void setParent(CommandContext args, CommandSender sender) throws CommandException {
Player player = plugin.checkPlayer(sender);
World world = player.getWorld();
LocalPlayer localPlayer = plugin.wrapPlayer(player);
String id = args.getString(0);
if (id.equalsIgnoreCase("__global__")) {
throw new CommandException("The region cannot be named __global__");
}
RegionIndex mgr = plugin.getGlobalRegionManager().get(world);
Region region = mgr.getRegion(id);
if (region == null) {
throw new CommandException("Could not find a target region by that ID.");
}
id = region.getId();
if (args.argsLength() == 1) {
try {
region.setParent(null);
} catch (CircularInheritanceException ignore) {
}
sender.sendMessage(ChatColor.YELLOW
+ "Parent of '" + region.getId() + "' cleared.");
} else {
String parentId = args.getString(1);
Region parent = mgr.getRegion(parentId);
if (parent == null) {
throw new CommandException("Could not find the parent region by that ID.");
}
if (region.isOwner(localPlayer)) {
plugin.checkPermission(sender, "worldguard.region.setparent.own." + id.toLowerCase());
} else if (region.isMember(localPlayer)) {
plugin.checkPermission(sender, "worldguard.region.setparent.member." + id.toLowerCase());
} else {
plugin.checkPermission(sender, "worldguard.region.setparent." + id.toLowerCase());
}
if (parent.isOwner(localPlayer)) {
plugin.checkPermission(sender, "worldguard.region.setparent.own." + parentId.toLowerCase());
} else if (parent.isMember(localPlayer)) {
plugin.checkPermission(sender, "worldguard.region.setparent.member." + parentId.toLowerCase());
} else {
plugin.checkPermission(sender, "worldguard.region.setparent." + parentId.toLowerCase());
}
try {
region.setParent(parent);
} catch (CircularInheritanceException e) {
throw new CommandException("Circular inheritance detected!");
}
sender.sendMessage(ChatColor.YELLOW
+ "Parent of '" + region.getId() + "' set to '"
+ parent.getId() + "'.");
}
try {
mgr.save();
} catch (ProtectionDatabaseException e) {
throw new CommandException("Failed to write regions: "
+ e.getMessage());
}
}
@Command(aliases = {"remove", "delete", "del", "rem"}, usage = "<id>",
desc = "Remove a region", min = 1, max = 1)
public void remove(CommandContext args, CommandSender sender) throws CommandException {
Player player = plugin.checkPlayer(sender);
World world = player.getWorld();
LocalPlayer localPlayer = plugin.wrapPlayer(player);
String id = args.getString(0);
RegionIndex mgr = plugin.getGlobalRegionManager().get(world);
Region region = mgr.getRegionExact(id);
if (region == null) {
throw new CommandException("Could not find a region by that ID.");
}
if (region.isOwner(localPlayer)) {
plugin.checkPermission(sender, "worldguard.region.remove.own." + id.toLowerCase());
} else if (region.isMember(localPlayer)) {
plugin.checkPermission(sender, "worldguard.region.remove.member." + id.toLowerCase());
} else {
plugin.checkPermission(sender, "worldguard.region.remove." + id.toLowerCase());
}
mgr.removeRegion(id);
sender.sendMessage(ChatColor.YELLOW
+ "Region '" + id + "' removed.");
try {
mgr.save();
} catch (ProtectionDatabaseException e) {
throw new CommandException("Failed to write regions: "
+ e.getMessage());
}
}
@Command(aliases = {"load", "reload"}, usage = "[world]",
desc = "Reload regions from file", max = 1)
@CommandPermissions({"worldguard.region.load"})
public void load(CommandContext args, CommandSender sender) throws CommandException {
World world = null;
if (args.argsLength() > 0) {
world = plugin.matchWorld(sender, args.getString(0));
}
if (world != null) {
RegionIndex mgr = plugin.getGlobalRegionManager().get(world);
try {
mgr.load();
sender.sendMessage(ChatColor.YELLOW
+ "Regions for '" + world.getName() + "' load.");
} catch (ProtectionDatabaseException e) {
throw new CommandException("Failed to read regions: "
+ e.getMessage());
}
} else {
for (World w : plugin.getServer().getWorlds()) {
RegionIndex mgr = plugin.getGlobalRegionManager().get(w);
try {
mgr.load();
} catch (ProtectionDatabaseException e) {
throw new CommandException("Failed to read regions: "
+ e.getMessage());
}
}
sender.sendMessage(ChatColor.YELLOW
+ "Region databases loaded.");
}
}
@Command(aliases = {"save", "write"}, usage = "[world]",
desc = "Re-save regions to file", max = 1)
@CommandPermissions({"worldguard.region.save"})
public void save(CommandContext args, CommandSender sender) throws CommandException {
World world = null;
if (args.argsLength() > 0) {
world = plugin.matchWorld(sender, args.getString(0));
}
if (world != null) {
RegionIndex mgr = plugin.getGlobalRegionManager().get(world);
try {
mgr.save();
sender.sendMessage(ChatColor.YELLOW
+ "Regions for '" + world.getName() + "' saved.");
} catch (ProtectionDatabaseException e) {
throw new CommandException("Failed to write regions: "
+ e.getMessage());
}
} else {
for (World w : plugin.getServer().getWorlds()) {
RegionIndex mgr = plugin.getGlobalRegionManager().get(w);
try {
mgr.save();
} catch (ProtectionDatabaseException e) {
throw new CommandException("Failed to write regions: "
+ e.getMessage());
}
}
sender.sendMessage(ChatColor.YELLOW
+ "Region databases saved.");
}
}
@Command(aliases = {"teleport", "tp"}, usage = "<id>", flags = "s",
desc = "Teleports you to the location associated with the region.", min = 1, max = 1)
@CommandPermissions({"worldguard.region.teleport"})
public void teleport(CommandContext args, CommandSender sender) throws CommandException {
final Player player = plugin.checkPlayer(sender);
final RegionIndex mgr = plugin.getGlobalRegionManager().get(player.getWorld());
String id = args.getString(0);
final Region region = mgr.getRegion(id);
if (region == null) {
if (!Region.isValidId(id)) {
throw new CommandException("Invalid region ID specified!");
}
throw new CommandException("A region with ID '" + id + "' doesn't exist.");
}
id = region.getId();
LocalPlayer localPlayer = plugin.wrapPlayer(player);
if (region.isOwner(localPlayer)) {
plugin.checkPermission(sender, "worldguard.region.teleport.own." + id.toLowerCase());
} else if (region.isMember(localPlayer)) {
plugin.checkPermission(sender, "worldguard.region.teleport.member." + id.toLowerCase());
} else {
plugin.checkPermission(sender, "worldguard.region.teleport." + id.toLowerCase());
}
final Location teleportLocation;
if (args.hasFlag('s')) {
teleportLocation = region.getFlag(DefaultFlag.SPAWN_LOC);
if (teleportLocation == null) {
throw new CommandException("The region has no spawn point associated.");
}
} else {
teleportLocation = region.getFlag(DefaultFlag.TELE_LOC);
if (teleportLocation == null) {
throw new CommandException("The region has no teleport point associated.");
}
}
player.teleport(BukkitUtil.toLocation(teleportLocation));
sender.sendMessage("Teleported you to the region '" + id + "'.");
}
}
@@ -0,0 +1,221 @@
// $Id$
/*
* WorldGuard
* Copyright (C) 2010 sk89q <http://www.sk89q.com>
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU 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 General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package com.sk89q.worldguard.bukkit.commands;
import org.bukkit.ChatColor;
import org.bukkit.World;
import org.bukkit.command.CommandSender;
import org.bukkit.entity.Player;
import com.sk89q.minecraft.util.commands.Command;
import com.sk89q.minecraft.util.commands.CommandContext;
import com.sk89q.minecraft.util.commands.CommandException;
import com.sk89q.worldguard.LocalPlayer;
import com.sk89q.worldguard.bukkit.WorldGuardPlugin;
import com.sk89q.worldguard.domains.DefaultDomain;
import com.sk89q.worldguard.region.Region;
import com.sk89q.worldguard.region.flags.DefaultFlag;
import com.sk89q.worldguard.region.indices.RegionIndex;
import com.sk89q.worldguard.region.stores.ProtectionDatabaseException;
import com.sk89q.worldguard.region.stores.RegionDBUtil;
// @TODO: A lot of code duplication here! Need to fix.
public class RegionMemberCommands {
private final WorldGuardPlugin plugin;
public RegionMemberCommands(WorldGuardPlugin plugin) {
this.plugin = plugin;
}
@Command(aliases = {"addmember", "addmember"}, usage = "<id> <members...>",
desc = "Add a member to a region", min = 2)
public void addMember(CommandContext args, CommandSender sender) throws CommandException {
Player player = plugin.checkPlayer(sender);
World world = player.getWorld();
LocalPlayer localPlayer = plugin.wrapPlayer(player);
String id = args.getString(0);
RegionIndex mgr = plugin.getGlobalRegionManager().get(world);
Region region = mgr.getRegion(id);
if (region == null) {
throw new CommandException("Could not find a region by that ID.");
}
id = region.getId();
if (region.isOwner(localPlayer)) {
plugin.checkPermission(sender, "worldguard.region.addmember.own." + id.toLowerCase());
} else if (region.isMember(localPlayer)) {
plugin.checkPermission(sender, "worldguard.region.addmember.member." + id.toLowerCase());
} else {
plugin.checkPermission(sender, "worldguard.region.addmember." + id.toLowerCase());
}
RegionDBUtil.addToDomain(region.getMembers(), args.getPaddedSlice(2, 0), 0);
sender.sendMessage(ChatColor.YELLOW
+ "Region '" + id + "' updated.");
try {
mgr.save();
} catch (ProtectionDatabaseException e) {
throw new CommandException("Failed to write regions: "
+ e.getMessage());
}
}
@Command(aliases = {"addowner", "addowner"}, usage = "<id> <owners...>",
desc = "Add an owner to a region", min = 2)
public void addOwner(CommandContext args, CommandSender sender) throws CommandException {
Player player = plugin.checkPlayer(sender);
World world = player.getWorld();
LocalPlayer localPlayer = plugin.wrapPlayer(player);
String id = args.getString(0);
RegionIndex mgr = plugin.getGlobalRegionManager().get(world);
Region region = mgr.getRegion(id);
if (region == null) {
throw new CommandException("Could not find a region by that ID.");
}
id = region.getId();
Boolean flag = region.getFlag(DefaultFlag.BUYABLE);
DefaultDomain owners = region.getOwners();
if (flag != null && flag && owners != null && owners.size() == 0) {
if (!plugin.hasPermission(player, "worldguard.region.unlimited")) {
int maxRegionCount = plugin.getGlobalStateManager().get(world).getMaxRegionCount(player);
if (maxRegionCount >= 0 && mgr.getRegionCountOfPlayer(localPlayer)
>= maxRegionCount) {
throw new CommandException("You already own the maximum allowed amount of regions.");
}
}
plugin.checkPermission(sender, "worldguard.region.addowner.unclaimed." + id.toLowerCase());
} else {
if (region.isOwner(localPlayer)) {
plugin.checkPermission(sender, "worldguard.region.addowner.own." + id.toLowerCase());
} else if (region.isMember(localPlayer)) {
plugin.checkPermission(sender, "worldguard.region.addowner.member." + id.toLowerCase());
} else {
plugin.checkPermission(sender, "worldguard.region.addowner." + id.toLowerCase());
}
}
RegionDBUtil.addToDomain(region.getOwners(), args.getPaddedSlice(2, 0), 0);
sender.sendMessage(ChatColor.YELLOW
+ "Region '" + id + "' updated.");
try {
mgr.save();
} catch (ProtectionDatabaseException e) {
throw new CommandException("Failed to write regions: "
+ e.getMessage());
}
}
@Command(aliases = {"removemember", "remmember", "removemem", "remmem"}, usage = "<id> <owners...>",
desc = "Remove an owner to a region", min = 2)
public void removeMember(CommandContext args, CommandSender sender) throws CommandException {
Player player = plugin.checkPlayer(sender);
World world = player.getWorld();
LocalPlayer localPlayer = plugin.wrapPlayer(player);
String id = args.getString(0);
RegionIndex mgr = plugin.getGlobalRegionManager().get(world);
Region region = mgr.getRegion(id);
if (region == null) {
throw new CommandException("Could not find a region by that ID.");
}
id = region.getId();
if (region.isOwner(localPlayer)) {
plugin.checkPermission(sender, "worldguard.region.removemember.own." + id.toLowerCase());
} else if (region.isMember(localPlayer)) {
plugin.checkPermission(sender, "worldguard.region.removemember.member." + id.toLowerCase());
} else {
plugin.checkPermission(sender, "worldguard.region.removemember." + id.toLowerCase());
}
RegionDBUtil.removeFromDomain(region.getMembers(), args.getPaddedSlice(2, 0), 0);
sender.sendMessage(ChatColor.YELLOW
+ "Region '" + id + "' updated.");
try {
mgr.save();
} catch (ProtectionDatabaseException e) {
throw new CommandException("Failed to write regions: "
+ e.getMessage());
}
}
@Command(aliases = {"removeowner", "remowner"}, usage = "<id> <owners...>",
desc = "Remove an owner to a region", min = 2)
public void removeOwner(CommandContext args,
CommandSender sender) throws CommandException {
Player player = plugin.checkPlayer(sender);
World world = player.getWorld();
LocalPlayer localPlayer = plugin.wrapPlayer(player);
String id = args.getString(0);
RegionIndex mgr = plugin.getGlobalRegionManager().get(world);
Region region = mgr.getRegion(id);
if (region == null) {
throw new CommandException("Could not find a region by that ID.");
}
id = region.getId();
if (region.isOwner(localPlayer)) {
plugin.checkPermission(sender, "worldguard.region.removeowner.own." + id.toLowerCase());
} else if (region.isMember(localPlayer)) {
plugin.checkPermission(sender, "worldguard.region.removeowner.member." + id.toLowerCase());
} else {
plugin.checkPermission(sender, "worldguard.region.removeowner." + id.toLowerCase());
}
RegionDBUtil.removeFromDomain(region.getOwners(), args.getPaddedSlice(2, 0), 0);
sender.sendMessage(ChatColor.YELLOW
+ "Region '" + id + "' updated.");
try {
mgr.save();
} catch (ProtectionDatabaseException e) {
throw new CommandException("Failed to write regions: "
+ e.getMessage());
}
}
}
Loaded 100 of 534 files, more files were not shown because too many files have changed in this diff. Show more