mirror of
https://github.com/EngineHub/WorldGuard.git
synced 2026-11-15 13:25:58 -05:00
Compare commits
111
Commits
6.0.0-beta-03
...
6.1
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
9cf85caf3c | ||
|
|
2f1343f408 | ||
|
|
3cb6c4e46f | ||
|
|
7f9b850288 | ||
|
|
e8d4f2fd84 | ||
|
|
f3891aaaf9 | ||
|
|
ea75549a29 | ||
|
|
fbd8206038 | ||
|
|
522ac459db | ||
|
|
255dd2d41a | ||
|
|
cf1716ff37 | ||
|
|
a277e69e9c | ||
|
|
ec5bb32510 | ||
|
|
8ddb7d4b99 | ||
|
|
3258bff2d1 | ||
|
|
8d7d32a2d2 | ||
|
|
a907eb2348 | ||
|
|
32132b5b0a | ||
|
|
c0c7c3215e | ||
|
|
ddf0f41061 | ||
|
|
d3ecbcb18a | ||
|
|
b7f4262978 | ||
|
|
60e6f92c64 | ||
|
|
98af7966cd | ||
|
|
99d042d260 | ||
|
|
c9d6166fcb | ||
|
|
752ccec150 | ||
|
|
91ccb95672 | ||
|
|
4caff457d3 | ||
|
|
a1a6ee7107 | ||
|
|
af157b88bd | ||
|
|
ea4f4c088b | ||
|
|
6559ed5c1a | ||
|
|
deddcf8dd2 | ||
|
|
dfe536a2d2 | ||
|
|
5bfb348354 | ||
|
|
afcf93b7b1 | ||
|
|
e1843624bb | ||
|
|
0f4e7b5061 | ||
|
|
869ead63bc | ||
|
|
6a6de7802b | ||
|
|
b50302d9d0 | ||
|
|
c841d74aaf | ||
|
|
09cce39aff | ||
|
|
e5b76a571b | ||
|
|
7c58fa4be6 | ||
|
|
f150a41d72 | ||
|
|
bca1c2bdb3 | ||
|
|
47a8bcc442 | ||
|
|
83cad75916 | ||
|
|
6b5a12105e | ||
|
|
451b679323 | ||
|
|
66a8bfd5b1 | ||
|
|
2a2b2f6f64 | ||
|
|
73dea11de2 | ||
|
|
9998a6c930 | ||
|
|
5111d40aaf | ||
|
|
972ccaed7e | ||
|
|
f7d36bc1f3 | ||
|
|
8073945af0 | ||
|
|
91353d6b01 | ||
|
|
bfbcc8dcf8 | ||
|
|
8f65798141 | ||
|
|
fdddb17d2f | ||
|
|
520f9e3fcf | ||
|
|
a3d2a1b127 | ||
|
|
7ecf73165b | ||
|
|
e90a7ed075 | ||
|
|
aae521b727 | ||
|
|
643345b459 | ||
|
|
a62d9f5617 | ||
|
|
2f3f76c8cf | ||
|
|
a03aaa45b1 | ||
|
|
372155b5c3 | ||
|
|
159de771bf | ||
|
|
41d922cb27 | ||
|
|
6a4fac63e8 | ||
|
|
3daf8db113 | ||
|
|
9c62a35e07 | ||
|
|
931f438b14 | ||
|
|
3109612c1b | ||
|
|
e4d63ffbcc | ||
|
|
866a554d30 | ||
|
|
ab2811ed2d | ||
|
|
8cc7bcc849 | ||
|
|
547e89b85d | ||
|
|
477f1188df | ||
|
|
d9e4b27cd2 | ||
|
|
37f39eaf66 | ||
|
|
223d22e79f | ||
|
|
04214a96eb | ||
|
|
f40cb69f38 | ||
|
|
6c1489d434 | ||
|
|
6fe63838f5 | ||
|
|
d883c22d64 | ||
|
|
3bd1c869f1 | ||
|
|
e7273aaf6f | ||
|
|
6e02f80f6c | ||
|
|
01276dfc62 | ||
|
|
f516fd5e54 | ||
|
|
79612915a7 | ||
|
|
f04f9093bc | ||
|
|
9dac950faf | ||
|
|
f2a8ff3f64 | ||
|
|
b78317dd42 | ||
|
|
048dd25099 | ||
|
|
0900289437 | ||
|
|
d8dd86dfe8 | ||
|
|
9a569d7ed8 | ||
|
|
53132ce83a | ||
|
|
c3bdc33215 |
No files matched your search
@@ -1,5 +1,87 @@
|
||||
# Changelog
|
||||
|
||||
## 6.1
|
||||
|
||||
* Added `exit-via-teleport` flag (default allow) to control exiting an exit=deny region via teleportation.
|
||||
* Added a `fall-damage` flag to control player damage caused by falling.
|
||||
* Added a `time-lock` flag to lock players' time of day. Valid values are from 0 to 24000 for absolute time, or +- any number for relative time.
|
||||
* Added a `weather-lock` flag to lock players' weather. Valid values are "clear" or "downfall". Unset to restore to normal world weather.
|
||||
* Added `-s` to the event debugging commands to show a stack trace rather than attempt to detect the causing plugin.
|
||||
* Added support for using the `-e` argument (sets an empty value for the flag) in the flag set command when the type of flag is of the 'set' type.
|
||||
* Added NPCs from the Citizens plugin to a whitelist so they are not protected.
|
||||
* Added support for Spigot's BlockExplodeEvent.
|
||||
* Changed tripwire to fall under the `use` flag.
|
||||
* Changed enderchests to fall under the `use` flag.
|
||||
* Changed vehicles and animals so they are not included in the `interact` flag.
|
||||
* Changed the display of custom blacklist messages to no longer include a period at the end.
|
||||
* Changed protection logic to consider connected chests.
|
||||
* Changed the heal and feed flags to increase values for players who are invincible (or in creative mode) but not decrease them.
|
||||
* Changed PvP protection to consider both attacker and defender locations.
|
||||
* Fixed missing protection data for some 1.8-added blocks.
|
||||
* Fixed compatibility issues with MC 1.7.
|
||||
* Fixed inverted daylight detectors not being protected.
|
||||
* Fixed spawn eggs not being included in protection.
|
||||
* Fixed piston blocking not working due to a bug in Spigot.
|
||||
* Fixed the blocking of certain invalid entity damage events.
|
||||
* Fixed creeper explosions not being blocked in certain situations with explosion related flags set.
|
||||
* Fixed "stickiness" with some position-related flags, sometimes resulting in rubber banding in the exit flags.
|
||||
* Fixed armor stands so that they are treated more like item frames than mobs.
|
||||
* Fixed blocks (e.g. sugar canes) adjacent to physics blocks (e.g. sand) not updating.
|
||||
* Fixed a NullPointerException that occurred sometimes when generating the scheduler section of the report function (`/wg report`).
|
||||
* Fixed the "no XP drops" configuration not functioning following a previous release.
|
||||
* Fixed changes to region ownership sometimes not triggering a region database save.
|
||||
* Fixed bucket protection displaying the "deny effect" even if bucket use was not prevented.
|
||||
* Fixed CommandFilter matching emoticons and other unwanted characters.
|
||||
* Fixed an exception occurring sometimes during game mode changes.
|
||||
* Fixed primed TNT being checked twice for TNT flags.
|
||||
|
||||
## 6.0 beta 5
|
||||
|
||||
MC 1.7.9, 1.7.10 and 1.8 (Spigot only) are supported.
|
||||
|
||||
* Added a feature to detect when another plugin (incorrectly) includes WorldGuard's files, causing errors.
|
||||
* Added a new `exit-override` flag that can be used on an entry=allow region that players can walk into from an entry=deny region.
|
||||
* Added a new `entry-deny-message` to change the "entry denied" message.
|
||||
* Added a new `exit-deny-message` to change the "exit denied" message.
|
||||
* Changed entry/exit blocking to disembark players from their vehicles.
|
||||
* Changed the PvP flag to no longer apply to self-attack.
|
||||
* Fixed [#3220](http://youtrack.sk89q.com/issue/WORLDGUARD-3220): Polygon regions sharing points
|
||||
* Fixed [#3216](http://youtrack.sk89q.com/issue/WORLDGUARD-3216): Polygon regions 'disappearing' or not working correctly
|
||||
* Fixed [#3315](http://youtrack.sk89q.com/issue/WORLDGUARD-3315): Invincibility flag and mode not blocking knockback from snowballs, etc.
|
||||
* Fixed [#3314](http://youtrack.sk89q.com/issue/WORLDGUARD-3314): Protection bypassable by getting a skeleton or creeper to target a player
|
||||
* Fixed [#3326](http://youtrack.sk89q.com/issue/WORLDGUARD-3326): Enderchests cannot be protected with the use flag
|
||||
* Fixed [#3327](http://youtrack.sk89q.com/issue/WORLDGUARD-3327): Fake players from some Forge mods are not being detected properly
|
||||
* Fixed [#3328](http://youtrack.sk89q.com/issue/WORLDGUARD-3328): TypeToken error with CraftBukkit 1.7 in `/wg report`
|
||||
* Fixed [#3086](http://youtrack.sk89q.com/issue/WORLDGUARD-3086): Region entry / exit messages overlap between seprate worlds
|
||||
* Fixed [#2542](http://youtrack.sk89q.com/issue/WORLDGUARD-2542): Exit deny regions don't handle respawn / logout consistently
|
||||
* Fixed [#2731](http://youtrack.sk89q.com/issue/WORLDGUARD-2731): Greeting / farewell messages don't understand region inheritance
|
||||
* Fixed [#3308](http://youtrack.sk89q.com/issue/WORLDGUARD-3308): Enderchest interaction block not functioning with blacklist.txt
|
||||
* Fixed [#3312](http://youtrack.sk89q.com/issue/WORLDGUARD-3312): PVP flag blocking enderpearl teleport fall damage
|
||||
* Fixed [#3309](http://youtrack.sk89q.com/issue/WORLDGUARD-3309): Inventory view commands being blocked in protected regions
|
||||
* Fixed [#3310](http://youtrack.sk89q.com/issue/WORLDGUARD-3310): USE flag is not allowing workbench usage
|
||||
* Fixed [#3330](http://youtrack.sk89q.com/issue/WORLDGUARD-3330): Build permissions preventing block placement
|
||||
* API: Added `BukkitUtil.toRegion(Chunk)`
|
||||
|
||||
## 6.0 beta 4
|
||||
|
||||
MC 1.7.9, 1.7.10 and 1.8 (Spigot only) are supported.
|
||||
|
||||
* Added better support for MC 1.8 blocks (regarding the use flag, etc.).
|
||||
* Added an an experimental "lite" version of WarmRoast to CPU profile your server (try it: `/wg profile -p`)
|
||||
* Added permissions for individual flag values (i.e. `worldguard.region.flag.flags.use.allow`).
|
||||
* Added support for slightly older versions of Bukkit 1.7.9.
|
||||
* Improved `/wg report`'s output (try it: `/wg report -p`)
|
||||
* Fixed armor stands not being protected properly.
|
||||
* Fixed lack of wood plate support with the `USE` flag.
|
||||
* Fixed left click also being blocked when only right click needed to be blocked.
|
||||
* Fixed items and paintings/item frames not decaying under some versions of Spigot.
|
||||
* Fixed parent-child inheritance so the child will always inherit the parent.
|
||||
* Fixed inheritance issues with a flag is set with a region group on a parent region.
|
||||
* Fixed high CPU usage when Citizens is also installed.
|
||||
* Fixed `on-acquire` in the blacklist so it also handles item transfers between inventories.
|
||||
* Fixed the blacklist not supporting color codes.
|
||||
* Changed the PvP flag so it applies to self-attack like in WG 5 (this change *may* be reverted).
|
||||
|
||||
## 6.0 beta 3
|
||||
|
||||
MC 1.7.10 and 1.8 (Spigot only) are supported.
|
||||
|
||||
+1
-5
@@ -4,7 +4,7 @@ This is a **major upgrade**. However, it is relatively well-tested because many
|
||||
|
||||
The version that you downloaded supports Minecraft 1.7.10 and 1.8.
|
||||
|
||||
**NEW DOCUMENTATION:** There is [new work-in-progress documentation](http://docs.enginehub.org/manual/worldguard/latest/). However, refer to the [older wiki](http://wiki.sk89q.com/wiki/WorldGuard) for missing pgaes.
|
||||
**NEW DOCUMENTATION:** There is [new work-in-progress documentation](http://docs.enginehub.org/manual/worldguard/latest/). However, refer to the [older wiki](http://wiki.sk89q.com/wiki/WorldGuard) for missing pages.
|
||||
|
||||
## Downgrading to 5.9
|
||||
|
||||
@@ -47,10 +47,6 @@ Plugins that utilize WorldGuard's API may not work anymore. They may crash with
|
||||
|
||||
* Spigot:
|
||||
* `settings.global-api-cache`, if enabled, will crash WG UUID lookups (fixed in Spigot build #1625)
|
||||
* EchoPet
|
||||
* Can't spawn pets ([issue #393](https://github.com/DSH105/EchoPet/issues/393))
|
||||
* CraftBook
|
||||
* Unable to use mechanics unless the `USE` flag is explicitly set to `ALLOW` ([CRAFTBOOK-3057](http://youtrack.sk89q.com/issue/CRAFTBOOK-3057))
|
||||
|
||||
## Other Changes
|
||||
|
||||
|
||||
@@ -37,4 +37,5 @@
|
||||
<allow pkg="com.google.common"/>
|
||||
<allow pkg="com.jolbox.bonecp"/>
|
||||
<allow pkg="org.flywaydb.core"/>
|
||||
<allow pkg="org.json.simple"/>
|
||||
</import-control>
|
||||
@@ -2,7 +2,7 @@
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
<groupId>com.sk89q</groupId>
|
||||
<artifactId>worldguard</artifactId>
|
||||
<version>6.0.0-beta-03</version>
|
||||
<version>6.1</version>
|
||||
<packaging>jar</packaging>
|
||||
|
||||
<!-- Project information -->
|
||||
@@ -66,8 +66,8 @@
|
||||
<url>http://maven.sk89q.com/repo/</url>
|
||||
</repository>
|
||||
<repository>
|
||||
<id>bukkit-repo</id>
|
||||
<url>http://repo.bukkit.org/content/groups/public</url>
|
||||
<id>spigot-repo</id>
|
||||
<url>https://hub.spigotmc.org/nexus/content/groups/public/</url>
|
||||
</repository>
|
||||
</repositories>
|
||||
|
||||
@@ -90,10 +90,17 @@
|
||||
</exclusions>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>com.sk89q.spigot</groupId>
|
||||
<artifactId>bukkit-classloader-check</artifactId>
|
||||
<version>1.8-R0.1-SNAPSHOT</version>
|
||||
<scope>runtime</scope>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>org.bukkit</groupId>
|
||||
<artifactId>bukkit</artifactId>
|
||||
<version>1.7.9-R0.3-SNAPSHOT</version>
|
||||
<version>1.8.6-R0.1-SNAPSHOT</version>
|
||||
<scope>compile</scope>
|
||||
<type>jar</type>
|
||||
</dependency>
|
||||
@@ -129,14 +136,6 @@
|
||||
<optional>true</optional>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>com.google.guava</groupId>
|
||||
<artifactId>guava</artifactId>
|
||||
<version>10.0.1</version> <!-- Bukkit only bundles 10.0.1 -->
|
||||
<scope>compile</scope> <!-- required runtime dependency -->
|
||||
<type>jar</type>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<!-- Contains parts of Guava that are not compatible
|
||||
between Bukkit 10.0.1 and 17+ -->
|
||||
@@ -388,6 +387,7 @@
|
||||
<include>org.flywaydb:flyway-core</include>
|
||||
<include>com.sk89q:squirrelid</include>
|
||||
<include>com.sk89q:guavabackport</include>
|
||||
<include>com.googlecode.json-simple:json-simple</include>
|
||||
</includes>
|
||||
</artifactSet>
|
||||
<relocations>
|
||||
@@ -403,6 +403,10 @@
|
||||
<pattern>com.sk89q.squirrelid</pattern>
|
||||
<shadedPattern>com.sk89q.worldguard.util.profile</shadedPattern>
|
||||
</relocation>
|
||||
<relocation>
|
||||
<pattern>org.json.simple</pattern>
|
||||
<shadedPattern>com.sk89q.worldguard.util.jsonsimple</shadedPattern>
|
||||
</relocation>
|
||||
</relocations>
|
||||
</configuration>
|
||||
</execution>
|
||||
@@ -456,6 +460,37 @@
|
||||
<tagNameFormat>@{project.version}</tagNameFormat>
|
||||
</configuration>
|
||||
</plugin>
|
||||
|
||||
<plugin>
|
||||
<groupId>org.apache.maven.plugins</groupId>
|
||||
<artifactId>maven-source-plugin</artifactId>
|
||||
<version>2.2.1</version>
|
||||
<executions>
|
||||
<execution>
|
||||
<id>attach-sources</id>
|
||||
<goals>
|
||||
<goal>jar</goal>
|
||||
</goals>
|
||||
</execution>
|
||||
</executions>
|
||||
</plugin>
|
||||
|
||||
<plugin>
|
||||
<groupId>org.apache.maven.plugins</groupId>
|
||||
<artifactId>maven-javadoc-plugin</artifactId>
|
||||
<version>2.8.1</version>
|
||||
<configuration>
|
||||
<additionalparam>-Xdoclint:none</additionalparam>
|
||||
</configuration>
|
||||
<executions>
|
||||
<execution>
|
||||
<id>attach-javadocs</id>
|
||||
<goals>
|
||||
<goal>jar</goal>
|
||||
</goals>
|
||||
</execution>
|
||||
</executions>
|
||||
</plugin>
|
||||
|
||||
<plugin>
|
||||
<groupId>org.apache.maven.plugins</groupId>
|
||||
@@ -487,43 +522,4 @@
|
||||
</plugin>
|
||||
</plugins>
|
||||
</build>
|
||||
|
||||
<profiles>
|
||||
<!-- Attach javadocs and source .jars -->
|
||||
<profile>
|
||||
<id>attach-docs</id>
|
||||
|
||||
<build>
|
||||
<plugins>
|
||||
<plugin>
|
||||
<groupId>org.apache.maven.plugins</groupId>
|
||||
<artifactId>maven-source-plugin</artifactId>
|
||||
<version>2.2.1</version>
|
||||
<executions>
|
||||
<execution>
|
||||
<id>attach-sources</id>
|
||||
<goals>
|
||||
<goal>jar</goal>
|
||||
</goals>
|
||||
</execution>
|
||||
</executions>
|
||||
</plugin>
|
||||
|
||||
<plugin>
|
||||
<groupId>org.apache.maven.plugins</groupId>
|
||||
<artifactId>maven-javadoc-plugin</artifactId>
|
||||
<version>2.8.1</version>
|
||||
<executions>
|
||||
<execution>
|
||||
<id>attach-javadocs</id>
|
||||
<goals>
|
||||
<goal>jar</goal>
|
||||
</goals>
|
||||
</execution>
|
||||
</executions>
|
||||
</plugin>
|
||||
</plugins>
|
||||
</build>
|
||||
</profile>
|
||||
</profiles>
|
||||
</project>
|
||||
@@ -24,6 +24,7 @@ import com.sk89q.worldguard.domains.Association;
|
||||
import com.sk89q.worldguard.protection.association.RegionAssociable;
|
||||
import com.sk89q.worldguard.protection.regions.ProtectedRegion;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.UUID;
|
||||
|
||||
public abstract class LocalPlayer implements RegionAssociable {
|
||||
@@ -94,14 +95,18 @@ public abstract class LocalPlayer implements RegionAssociable {
|
||||
public abstract boolean hasPermission(String perm);
|
||||
|
||||
@Override
|
||||
public Association getAssociation(ProtectedRegion region) {
|
||||
if (region.isOwner(this)) {
|
||||
return Association.OWNER;
|
||||
} else if (region.isMember(this)) {
|
||||
return Association.MEMBER;
|
||||
} else {
|
||||
return Association.NON_MEMBER;
|
||||
public Association getAssociation(List<ProtectedRegion> regions) {
|
||||
boolean member = false;
|
||||
|
||||
for (ProtectedRegion region : regions) {
|
||||
if (region.isOwner(this)) {
|
||||
return Association.OWNER;
|
||||
} else if (!member && region.isMember(this)) {
|
||||
member = true;
|
||||
}
|
||||
}
|
||||
|
||||
return member ? Association.MEMBER : Association.NON_MEMBER;
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
@@ -29,6 +29,7 @@ import com.sk89q.worldguard.blacklist.target.TargetMatcherParser;
|
||||
import com.sk89q.guavabackport.cache.CacheBuilder;
|
||||
import com.sk89q.guavabackport.cache.CacheLoader;
|
||||
import com.sk89q.guavabackport.cache.LoadingCache;
|
||||
import com.sk89q.worldguard.bukkit.commands.CommandUtils;
|
||||
import org.bukkit.ChatColor;
|
||||
|
||||
import java.io.BufferedReader;
|
||||
@@ -184,10 +185,10 @@ public abstract class Blacklist {
|
||||
entry.setIgnorePermissions(parts[1].split(","));
|
||||
|
||||
} else if (parts[0].equalsIgnoreCase("message")) {
|
||||
entry.setMessage(parts[1].trim());
|
||||
entry.setMessage(CommandUtils.replaceColorMacros(parts[1].trim()));
|
||||
|
||||
} else if (parts[0].equalsIgnoreCase("comment")) {
|
||||
entry.setComment(parts[1].trim());
|
||||
entry.setComment(CommandUtils.replaceColorMacros(parts[1].trim()));
|
||||
|
||||
} else {
|
||||
boolean found = false;
|
||||
|
||||
@@ -44,7 +44,7 @@ public class TellAction extends RepeatGuardedAction {
|
||||
|
||||
if (event.getPlayer() != null) {
|
||||
if (message != null) {
|
||||
event.getPlayer().printRaw(ChatColor.YELLOW + String.format(message, event.getTarget().getFriendlyName()) + ".");
|
||||
event.getPlayer().printRaw(ChatColor.YELLOW + String.format(message, event.getTarget().getFriendlyName()));
|
||||
} else {
|
||||
event.getPlayer().printRaw(ChatColor.YELLOW + "You're not allowed to " + event.getDescription() + " " +
|
||||
event.getTarget().getFriendlyName() + ".");
|
||||
|
||||
@@ -19,6 +19,7 @@
|
||||
|
||||
package com.sk89q.worldguard.bukkit;
|
||||
|
||||
import com.google.common.collect.ImmutableList;
|
||||
import com.sk89q.worldedit.BlockVector;
|
||||
import com.sk89q.worldedit.Vector;
|
||||
import com.sk89q.worldedit.blocks.BlockID;
|
||||
@@ -26,28 +27,23 @@ import com.sk89q.worldedit.blocks.BlockType;
|
||||
import com.sk89q.worldedit.blocks.ItemID;
|
||||
import com.sk89q.worldguard.blacklist.target.MaterialTarget;
|
||||
import com.sk89q.worldguard.blacklist.target.Target;
|
||||
import org.bukkit.ChatColor;
|
||||
import org.bukkit.Location;
|
||||
import org.bukkit.Material;
|
||||
import org.bukkit.Server;
|
||||
import org.bukkit.World;
|
||||
import com.sk89q.worldguard.protection.regions.ProtectedCuboidRegion;
|
||||
import com.sk89q.worldguard.protection.regions.ProtectedRegion;
|
||||
import org.bukkit.*;
|
||||
import org.bukkit.block.Block;
|
||||
import org.bukkit.entity.Entity;
|
||||
import org.bukkit.entity.ExperienceOrb;
|
||||
import org.bukkit.entity.FallingBlock;
|
||||
import org.bukkit.entity.Item;
|
||||
import org.bukkit.entity.LivingEntity;
|
||||
import org.bukkit.entity.Player;
|
||||
import org.bukkit.entity.TNTPrimed;
|
||||
import org.bukkit.entity.Tameable;
|
||||
import org.bukkit.entity.*;
|
||||
import org.bukkit.inventory.ItemStack;
|
||||
|
||||
import java.lang.reflect.Method;
|
||||
import java.util.Collection;
|
||||
import java.util.List;
|
||||
|
||||
import static com.google.common.base.Preconditions.checkNotNull;
|
||||
|
||||
public class BukkitUtil {
|
||||
|
||||
private static Method ONLINE_PLAYERS_METHOD;
|
||||
|
||||
private BukkitUtil() {
|
||||
|
||||
}
|
||||
@@ -93,6 +89,20 @@ public class BukkitUtil {
|
||||
return new Location(world, vec.getX(), vec.getY(), vec.getZ());
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a dummy region that encompasses the size of a chunk.
|
||||
*
|
||||
* @param chunk The chunk
|
||||
* @return The dummy region
|
||||
*/
|
||||
public static ProtectedRegion toRegion(Chunk chunk) {
|
||||
World world = chunk.getWorld();
|
||||
|
||||
int minX = chunk.getX() << 4;
|
||||
int minZ = chunk.getZ() << 4;
|
||||
return new ProtectedCuboidRegion("_", new BlockVector(minX, 0, minZ), new BlockVector(minX + 15, world.getMaxHeight(), minZ + 15));
|
||||
}
|
||||
|
||||
/**
|
||||
* Matches one player based on name.
|
||||
*
|
||||
@@ -350,4 +360,42 @@ public class BukkitUtil {
|
||||
return new MaterialTarget(material.getId(), (short) 0);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get a collection of the currently online players.
|
||||
*
|
||||
* @return The online players
|
||||
*/
|
||||
@SuppressWarnings("unchecked")
|
||||
public static Collection<? extends Player> getOnlinePlayers() {
|
||||
try {
|
||||
return Bukkit.getServer().getOnlinePlayers();
|
||||
} catch (NoSuchMethodError ignored) {
|
||||
}
|
||||
|
||||
try {
|
||||
if (ONLINE_PLAYERS_METHOD == null) {
|
||||
ONLINE_PLAYERS_METHOD = getOnlinePlayersMethod();
|
||||
}
|
||||
|
||||
Object result = ONLINE_PLAYERS_METHOD.invoke(Bukkit.getServer());
|
||||
if (result instanceof Player[]) {
|
||||
return ImmutableList.copyOf((Player[]) result);
|
||||
} else if (result instanceof Collection<?>) {
|
||||
return (Collection<? extends Player>) result;
|
||||
} else {
|
||||
throw new RuntimeException("Result of getOnlinePlayers() call was not a known data type");
|
||||
}
|
||||
} catch (Exception e) {
|
||||
throw new RuntimeException("WorldGuard is not compatible with this version of Bukkit", e);
|
||||
}
|
||||
}
|
||||
|
||||
private static Method getOnlinePlayersMethod() throws NoSuchMethodException {
|
||||
try {
|
||||
return Server.class.getMethod("getOnlinePlayers");
|
||||
} catch (NoSuchMethodException e1) {
|
||||
return Server.class.getMethod("_INVALID_getOnlinePlayers");
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
@@ -20,15 +20,13 @@
|
||||
package com.sk89q.worldguard.bukkit;
|
||||
|
||||
import com.google.common.collect.ImmutableMap;
|
||||
import com.sk89q.commandbook.CommandBook;
|
||||
import com.sk89q.commandbook.GodComponent;
|
||||
import com.sk89q.util.yaml.YAMLFormat;
|
||||
import com.sk89q.util.yaml.YAMLProcessor;
|
||||
import com.sk89q.worldguard.LocalPlayer;
|
||||
import com.sk89q.worldguard.protection.managers.storage.file.DirectoryYamlDriver;
|
||||
import com.sk89q.worldguard.protection.managers.storage.DriverType;
|
||||
import com.sk89q.worldguard.protection.managers.storage.RegionDriver;
|
||||
import com.sk89q.worldguard.protection.managers.storage.file.DirectoryYamlDriver;
|
||||
import com.sk89q.worldguard.protection.managers.storage.sql.SQLDriver;
|
||||
import com.sk89q.worldguard.session.handler.WaterBreathing;
|
||||
import com.sk89q.worldguard.util.report.Unreported;
|
||||
import com.sk89q.worldguard.util.sql.DataSourceConfig;
|
||||
import org.bukkit.World;
|
||||
@@ -37,9 +35,7 @@ import org.bukkit.entity.Player;
|
||||
import java.io.File;
|
||||
import java.io.IOException;
|
||||
import java.util.HashMap;
|
||||
import java.util.HashSet;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
import java.util.concurrent.ConcurrentHashMap;
|
||||
import java.util.concurrent.ConcurrentMap;
|
||||
import java.util.logging.Logger;
|
||||
@@ -79,12 +75,9 @@ public class ConfigurationManager {
|
||||
@Unreported private WorldGuardPlugin plugin;
|
||||
@Unreported private ConcurrentMap<String, WorldConfiguration> worlds;
|
||||
@Unreported private YAMLProcessor config;
|
||||
@Deprecated @Unreported private Set<String> hasGodMode = new HashSet<String>();
|
||||
@Unreported private Set<String> hasAmphibious = new HashSet<String>();
|
||||
|
||||
private boolean hasCommandBookGodMode = false;
|
||||
|
||||
public boolean useRegionsScheduler;
|
||||
public boolean useRegionsCreatureSpawnEvent;
|
||||
public boolean activityHaltToggle = false;
|
||||
public boolean useGodPermission;
|
||||
@@ -152,7 +145,6 @@ public class ConfigurationManager {
|
||||
}
|
||||
|
||||
config.removeProperty("suppress-tick-sync-warnings");
|
||||
useRegionsScheduler = config.getBoolean("regions.use-scheduler", true);
|
||||
migrateRegionsToUuid = config.getBoolean("regions.uuid-migration.perform-on-next-start", true);
|
||||
keepUnresolvedNames = config.getBoolean("regions.uuid-migration.keep-names-that-lack-uuids", true);
|
||||
useRegionsCreatureSpawnEvent = config.getBoolean("regions.use-creature-spawn-event", true);
|
||||
@@ -242,37 +234,6 @@ public class ConfigurationManager {
|
||||
return config;
|
||||
}
|
||||
|
||||
/**
|
||||
* Forget a player.
|
||||
*
|
||||
* @param player The player to forget about
|
||||
*/
|
||||
public void forgetPlayer(LocalPlayer player) {
|
||||
hasGodMode.remove(player.getName());
|
||||
hasAmphibious.remove(player.getName());
|
||||
}
|
||||
|
||||
/**
|
||||
* Enable god mode for a player.
|
||||
*
|
||||
* @param player The player to enable god mode for.
|
||||
*/
|
||||
@Deprecated
|
||||
public void enableGodMode(Player player) {
|
||||
|
||||
hasGodMode.add(player.getName());
|
||||
}
|
||||
|
||||
/**
|
||||
* Disable god mode for a player.
|
||||
*
|
||||
* @param player The player to disable godmode for
|
||||
*/
|
||||
@Deprecated
|
||||
public void disableGodMode(Player player) {
|
||||
hasGodMode.remove(player.getName());
|
||||
}
|
||||
|
||||
/**
|
||||
* Check to see if god mode is enabled for a player.
|
||||
*
|
||||
@@ -280,13 +241,7 @@ public class ConfigurationManager {
|
||||
* @return Whether the player has godmode through WorldGuard or CommandBook
|
||||
*/
|
||||
public boolean hasGodMode(Player player) {
|
||||
if (hasCommandBookGodMode) {
|
||||
GodComponent god = CommandBook.inst().getComponentManager().getComponent(GodComponent.class);
|
||||
if (god != null) {
|
||||
return god.hasGodMode(player);
|
||||
}
|
||||
}
|
||||
return hasGodMode.contains(player.getName());
|
||||
return plugin.getSessionManager().get(player).isInvincible(player);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -295,7 +250,10 @@ public class ConfigurationManager {
|
||||
* @param player The player to enable amphibious mode for
|
||||
*/
|
||||
public void enableAmphibiousMode(Player player) {
|
||||
hasAmphibious.add(player.getName());
|
||||
WaterBreathing handler = plugin.getSessionManager().get(player).getHandler(WaterBreathing.class);
|
||||
if (handler != null) {
|
||||
handler.setWaterBreathing(true);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -304,7 +262,10 @@ public class ConfigurationManager {
|
||||
* @param player The player to disable amphibious mode for
|
||||
*/
|
||||
public void disableAmphibiousMode(Player player) {
|
||||
hasAmphibious.remove(player.getName());
|
||||
WaterBreathing handler = plugin.getSessionManager().get(player).getHandler(WaterBreathing.class);
|
||||
if (handler != null) {
|
||||
handler.setWaterBreathing(false);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -314,7 +275,8 @@ public class ConfigurationManager {
|
||||
* @return Whether {@code player} has amphibious mode
|
||||
*/
|
||||
public boolean hasAmphibiousMode(Player player) {
|
||||
return hasAmphibious.contains(player.getName());
|
||||
WaterBreathing handler = plugin.getSessionManager().get(player).getHandler(WaterBreathing.class);
|
||||
return handler != null && handler.hasWaterBreathing();
|
||||
}
|
||||
|
||||
public void updateCommandBookGodMode() {
|
||||
|
||||
@@ -19,6 +19,7 @@
|
||||
|
||||
package com.sk89q.worldguard.bukkit;
|
||||
|
||||
import com.google.common.collect.ImmutableList;
|
||||
import com.google.common.collect.Lists;
|
||||
import com.google.common.util.concurrent.Futures;
|
||||
import com.google.common.util.concurrent.ListeningExecutorService;
|
||||
@@ -39,10 +40,15 @@ import com.sk89q.worldguard.bukkit.event.player.ProcessPlayerEvent;
|
||||
import com.sk89q.worldguard.bukkit.listener.*;
|
||||
import com.sk89q.worldguard.bukkit.util.Events;
|
||||
import com.sk89q.worldguard.protection.GlobalRegionManager;
|
||||
import com.sk89q.worldguard.protection.flags.Flag;
|
||||
import com.sk89q.worldguard.protection.managers.RegionManager;
|
||||
import com.sk89q.worldguard.protection.managers.storage.StorageException;
|
||||
import com.sk89q.worldguard.protection.regions.ProtectedCuboidRegion;
|
||||
import com.sk89q.worldguard.protection.regions.ProtectedRegion;
|
||||
import com.sk89q.worldguard.protection.util.UnresolvedNamesException;
|
||||
import com.sk89q.worldguard.session.SessionManager;
|
||||
import com.sk89q.worldguard.util.concurrent.EvenMoreExecutors;
|
||||
import com.sk89q.worldguard.util.logging.ClassSourceValidator;
|
||||
import com.sk89q.worldguard.util.logging.RecordMessagePrefixer;
|
||||
import com.sk89q.worldguard.util.task.SimpleSupervisor;
|
||||
import com.sk89q.worldguard.util.task.Supervisor;
|
||||
@@ -85,7 +91,7 @@ public class WorldGuardPlugin extends JavaPlugin {
|
||||
private final ConfigurationManager configuration = new ConfigurationManager(this);
|
||||
private final RegionContainer regionContainer = new RegionContainer(this);
|
||||
private final GlobalRegionManager globalRegionManager = new GlobalRegionManager(this, regionContainer);
|
||||
private FlagStateManager flagStateManager;
|
||||
private SessionManager sessionManager;
|
||||
private final Supervisor supervisor = new SimpleSupervisor();
|
||||
private ListeningExecutorService executorService;
|
||||
private ProfileService profileService;
|
||||
@@ -126,9 +132,16 @@ public class WorldGuardPlugin extends JavaPlugin {
|
||||
|
||||
executorService = MoreExecutors.listeningDecorator(EvenMoreExecutors.newBoundedCachedThreadPool(0, 1, 20));
|
||||
|
||||
sessionManager = new SessionManager(this);
|
||||
|
||||
// Set the proper command injector
|
||||
commands.setInjector(new SimpleInjector(this));
|
||||
|
||||
// Catch bad things being done by naughty plugins that include
|
||||
// WorldGuard's classes
|
||||
ClassSourceValidator verifier = new ClassSourceValidator(this);
|
||||
verifier.reportMismatches(ImmutableList.of(WGBukkit.class, ProtectedRegion.class, ProtectedCuboidRegion.class, Flag.class));
|
||||
|
||||
// Register command classes
|
||||
final CommandsManagerRegistration reg = new CommandsManagerRegistration(this, commands);
|
||||
reg.register(ToggleCommands.class);
|
||||
@@ -164,14 +177,10 @@ public class WorldGuardPlugin extends JavaPlugin {
|
||||
log.info("Loading region data...");
|
||||
regionContainer.initialize();
|
||||
|
||||
flagStateManager = new FlagStateManager(this);
|
||||
|
||||
if (configuration.useRegionsScheduler) {
|
||||
getServer().getScheduler().scheduleSyncRepeatingTask(this, flagStateManager,
|
||||
FlagStateManager.RUN_DELAY, FlagStateManager.RUN_DELAY);
|
||||
}
|
||||
getServer().getScheduler().scheduleSyncRepeatingTask(this, sessionManager, SessionManager.RUN_DELAY, SessionManager.RUN_DELAY);
|
||||
|
||||
// Register events
|
||||
getServer().getPluginManager().registerEvents(sessionManager, this);
|
||||
(new WorldGuardPlayerListener(this)).registerEvents();
|
||||
(new WorldGuardBlockListener(this)).registerEvents();
|
||||
(new WorldGuardEntityListener(this)).registerEvents();
|
||||
@@ -186,10 +195,12 @@ public class WorldGuardPlugin extends JavaPlugin {
|
||||
(new ChestProtectionListener(this)).registerEvents();
|
||||
(new RegionProtectionListener(this)).registerEvents();
|
||||
(new RegionFlagsListener(this)).registerEvents();
|
||||
(new WorldRulesListener(this)).registerEvents();
|
||||
(new BlockedPotionsListener(this)).registerEvents();
|
||||
(new EventAbstractionListener(this)).registerEvents();
|
||||
(new PlayerModesListener(this)).registerEvents();
|
||||
(new BuildPermissionListener(this)).registerEvents();
|
||||
(new InvincibilityListener(this)).registerEvents();
|
||||
if ("true".equalsIgnoreCase(System.getProperty("worldguard.debug.listener"))) {
|
||||
(new DebuggingListener(this, log)).registerEvents();
|
||||
}
|
||||
@@ -207,7 +218,7 @@ public class WorldGuardPlugin extends JavaPlugin {
|
||||
}
|
||||
worldListener.registerEvents();
|
||||
|
||||
for (Player player : getServer().getOnlinePlayers()) {
|
||||
for (Player player : BukkitUtil.getOnlinePlayers()) {
|
||||
ProcessPlayerEvent event = new ProcessPlayerEvent(player);
|
||||
Events.fire(event);
|
||||
}
|
||||
@@ -327,8 +338,8 @@ public class WorldGuardPlugin extends JavaPlugin {
|
||||
*
|
||||
* @return The flag state manager
|
||||
*/
|
||||
public FlagStateManager getFlagStateManager() {
|
||||
return flagStateManager;
|
||||
public SessionManager getSessionManager() {
|
||||
return sessionManager;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -462,7 +473,7 @@ public class WorldGuardPlugin extends JavaPlugin {
|
||||
// Invoke the permissions resolver
|
||||
if (sender instanceof Player) {
|
||||
Player player = (Player) sender;
|
||||
return PermissionsResolverManager.getInstance().hasPermission(player.getWorld().getName(), player.getName(), perm);
|
||||
return PermissionsResolverManager.getInstance().hasPermission(player.getWorld().getName(), player, perm);
|
||||
}
|
||||
|
||||
return false;
|
||||
@@ -510,7 +521,7 @@ public class WorldGuardPlugin extends JavaPlugin {
|
||||
* @return A {@link List} of players who match {@code filter}
|
||||
*/
|
||||
public List<Player> matchPlayerNames(String filter) {
|
||||
Collection<? extends Player> players = getServer().getOnlinePlayers();
|
||||
Collection<? extends Player> players = BukkitUtil.getOnlinePlayers();
|
||||
|
||||
filter = filter.toLowerCase();
|
||||
|
||||
@@ -591,12 +602,12 @@ public class WorldGuardPlugin extends JavaPlugin {
|
||||
public Iterable<? extends Player> matchPlayers(CommandSender source, String filter)
|
||||
throws CommandException {
|
||||
|
||||
if (getServer().getOnlinePlayers().isEmpty()) {
|
||||
if (BukkitUtil.getOnlinePlayers().isEmpty()) {
|
||||
throw new CommandException("No players matched query.");
|
||||
}
|
||||
|
||||
if (filter.equals("*")) {
|
||||
return checkPlayerMatch(Lists.newArrayList(getServer().getOnlinePlayers()));
|
||||
return checkPlayerMatch(Lists.newArrayList(BukkitUtil.getOnlinePlayers()));
|
||||
}
|
||||
|
||||
// Handle special hash tag groups
|
||||
@@ -608,7 +619,7 @@ public class WorldGuardPlugin extends JavaPlugin {
|
||||
Player sourcePlayer = checkPlayer(source);
|
||||
World sourceWorld = sourcePlayer.getWorld();
|
||||
|
||||
for (Player player : getServer().getOnlinePlayers()) {
|
||||
for (Player player : BukkitUtil.getOnlinePlayers()) {
|
||||
if (player.getWorld().equals(sourceWorld)) {
|
||||
players.add(player);
|
||||
}
|
||||
@@ -624,7 +635,7 @@ public class WorldGuardPlugin extends JavaPlugin {
|
||||
org.bukkit.util.Vector sourceVector
|
||||
= sourcePlayer.getLocation().toVector();
|
||||
|
||||
for (Player player : getServer().getOnlinePlayers()) {
|
||||
for (Player player : BukkitUtil.getOnlinePlayers()) {
|
||||
if (player.getWorld().equals(sourceWorld)
|
||||
&& player.getLocation().toVector().distanceSquared(
|
||||
sourceVector) < 900) {
|
||||
@@ -916,7 +927,7 @@ public class WorldGuardPlugin extends JavaPlugin {
|
||||
public void broadcastNotification(String msg) {
|
||||
getServer().broadcast(msg, "worldguard.notify");
|
||||
Set<Permissible> subs = getServer().getPluginManager().getPermissionSubscriptions("worldguard.notify");
|
||||
for (Player player : getServer().getOnlinePlayers()) {
|
||||
for (Player player : BukkitUtil.getOnlinePlayers()) {
|
||||
if (!(subs.contains(player) && player.hasPermission("worldguard.notify")) &&
|
||||
hasPermission(player, "worldguard.notify")) { // Make sure the player wasn't already broadcasted to.
|
||||
player.sendMessage(msg);
|
||||
@@ -925,15 +936,6 @@ public class WorldGuardPlugin extends JavaPlugin {
|
||||
log.info(msg);
|
||||
}
|
||||
|
||||
/**
|
||||
* Forgets a player.
|
||||
*
|
||||
* @param player The player to remove state information for
|
||||
*/
|
||||
public void forgetPlayer(Player player) {
|
||||
flagStateManager.forget(player);
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks to see if a player can build at a location. This will return
|
||||
* true if region protection is disabled.
|
||||
@@ -994,7 +996,7 @@ public class WorldGuardPlugin extends JavaPlugin {
|
||||
* @return The message with macros replaced
|
||||
*/
|
||||
public String replaceMacros(CommandSender sender, String message) {
|
||||
Collection<? extends Player> online = getServer().getOnlinePlayers();
|
||||
Collection<? extends Player> online = BukkitUtil.getOnlinePlayers();
|
||||
|
||||
message = message.replace("%name%", toName(sender));
|
||||
message = message.replace("%id%", toUniqueName(sender));
|
||||
|
||||
@@ -20,21 +20,17 @@
|
||||
package com.sk89q.worldguard.bukkit.cause;
|
||||
|
||||
import com.google.common.base.Joiner;
|
||||
import com.google.common.collect.Sets;
|
||||
import com.sk89q.worldguard.bukkit.internal.WGMetadata;
|
||||
import org.bukkit.block.Block;
|
||||
import org.bukkit.entity.Entity;
|
||||
import org.bukkit.entity.EntityType;
|
||||
import org.bukkit.entity.Player;
|
||||
import org.bukkit.entity.Projectile;
|
||||
import org.bukkit.entity.TNTPrimed;
|
||||
import org.bukkit.entity.Tameable;
|
||||
import org.bukkit.entity.Vehicle;
|
||||
import org.bukkit.entity.*;
|
||||
import org.bukkit.metadata.Metadatable;
|
||||
|
||||
import javax.annotation.Nullable;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
import java.util.Set;
|
||||
|
||||
import static com.google.common.base.Preconditions.checkNotNull;
|
||||
|
||||
@@ -47,21 +43,36 @@ import static com.google.common.base.Preconditions.checkNotNull;
|
||||
* is the initiator, while the arrow is merely controlled by the player to
|
||||
* hit the item frame.</p>
|
||||
*/
|
||||
public class Cause {
|
||||
public final class Cause {
|
||||
|
||||
private static final String CAUSE_KEY = "worldguard.cause";
|
||||
private static final Cause UNKNOWN = new Cause(Collections.emptyList());
|
||||
private static final Cause UNKNOWN = new Cause(Collections.emptyList(), false);
|
||||
|
||||
private final List<Object> causes;
|
||||
private final boolean indirect;
|
||||
|
||||
/**
|
||||
* Create a new instance.
|
||||
*
|
||||
* @param causes a list of causes
|
||||
* @param indirect whether the cause is indirect
|
||||
*/
|
||||
private Cause(List<Object> causes) {
|
||||
private Cause(List<Object> causes, boolean indirect) {
|
||||
checkNotNull(causes);
|
||||
this.causes = causes;
|
||||
this.indirect = indirect;
|
||||
}
|
||||
|
||||
/**
|
||||
* Test whether the traced cause is indirect.
|
||||
*
|
||||
* <p>If the cause is indirect, then the root cause may not be notified,
|
||||
* for example.</p>
|
||||
*
|
||||
* @return true if the cause is indirect
|
||||
*/
|
||||
public boolean isIndirect() {
|
||||
return indirect;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -118,6 +129,17 @@ public class Cause {
|
||||
return null;
|
||||
}
|
||||
|
||||
@Nullable
|
||||
public Entity getFirstNonPlayerEntity() {
|
||||
for (Object object : causes) {
|
||||
if (object instanceof Entity && !(object instanceof Player)) {
|
||||
return (Entity) object;
|
||||
}
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
@Nullable
|
||||
public Block getFirstBlock() {
|
||||
for (Object object : causes) {
|
||||
@@ -155,44 +177,6 @@ public class Cause {
|
||||
return Joiner.on(" | ").join(causes);
|
||||
}
|
||||
|
||||
/**
|
||||
* Expand an cause object.
|
||||
*
|
||||
* @param list the list to add elements to
|
||||
* @param element an array of objects
|
||||
*/
|
||||
private static void expand(List<Object> list, @Nullable Object ... element) {
|
||||
if (element != null) {
|
||||
for (Object o : element) {
|
||||
if (o == null) {
|
||||
continue;
|
||||
}
|
||||
|
||||
if (o instanceof TNTPrimed) {
|
||||
expand(list, ((TNTPrimed) o).getSource());
|
||||
} else if (o instanceof Projectile) {
|
||||
expand(list, ((Projectile) o).getShooter());
|
||||
} else if (o instanceof Vehicle) {
|
||||
expand(list, ((Vehicle) o).getPassenger());
|
||||
} else if (o instanceof Tameable) {
|
||||
expand(list, ((Tameable) o).getOwner());
|
||||
}
|
||||
|
||||
// Add manually tracked parent causes
|
||||
Object source = o;
|
||||
int index = list.size();
|
||||
while (source instanceof Metadatable && !(source instanceof Block)) {
|
||||
source = WGMetadata.getIfPresent((Metadatable) source, CAUSE_KEY, Object.class);
|
||||
if (source != null) {
|
||||
list.add(index, source);
|
||||
}
|
||||
}
|
||||
|
||||
list.add(o);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a new instance with the given objects as the cause,
|
||||
* where the first-most object is the initial initiator and those
|
||||
@@ -201,11 +185,11 @@ public class Cause {
|
||||
* @param cause an array of causing objects
|
||||
* @return a cause
|
||||
*/
|
||||
public static Cause create(@Nullable Object ... cause) {
|
||||
public static Cause create(@Nullable Object... cause) {
|
||||
if (cause != null) {
|
||||
List<Object> causes = new ArrayList<Object>(cause.length);
|
||||
expand(causes, cause);
|
||||
return new Cause(causes);
|
||||
Builder builder = new Builder(cause.length);
|
||||
builder.addAll(cause);
|
||||
return builder.build();
|
||||
} else {
|
||||
return UNKNOWN;
|
||||
}
|
||||
@@ -240,4 +224,60 @@ public class Cause {
|
||||
WGMetadata.put(target, CAUSE_KEY, parent);
|
||||
}
|
||||
|
||||
/**
|
||||
* Builds causes.
|
||||
*/
|
||||
private static final class Builder {
|
||||
private final List<Object> causes;
|
||||
private final Set<Object> seen = Sets.newHashSet();
|
||||
private boolean indirect;
|
||||
|
||||
private Builder(int expectedSize) {
|
||||
this.causes = new ArrayList<Object>(expectedSize);
|
||||
}
|
||||
|
||||
private void addAll(@Nullable Object... element) {
|
||||
if (element != null) {
|
||||
for (Object o : element) {
|
||||
if (o == null || seen.contains(o)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
seen.add(o);
|
||||
|
||||
if (o instanceof TNTPrimed) {
|
||||
addAll(((TNTPrimed) o).getSource());
|
||||
} else if (o instanceof Projectile) {
|
||||
addAll(((Projectile) o).getShooter());
|
||||
} else if (o instanceof Vehicle) {
|
||||
addAll(((Vehicle) o).getPassenger());
|
||||
} else if (o instanceof Creature && ((Creature) o).getTarget() != null) {
|
||||
indirect = true;
|
||||
addAll(((Creature) o).getTarget());
|
||||
} else if (o instanceof Tameable) {
|
||||
indirect = true;
|
||||
addAll(((Tameable) o).getOwner());
|
||||
}
|
||||
|
||||
// Add manually tracked parent causes
|
||||
Object source = o;
|
||||
int index = causes.size();
|
||||
while (source instanceof Metadatable && !(source instanceof Block)) {
|
||||
source = WGMetadata.getIfPresent((Metadatable) source, CAUSE_KEY, Object.class);
|
||||
if (source != null) {
|
||||
causes.add(index, source);
|
||||
seen.add(source);
|
||||
}
|
||||
}
|
||||
|
||||
causes.add(o);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public Cause build() {
|
||||
return new Cause(causes, indirect);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
@@ -20,6 +20,11 @@
|
||||
package com.sk89q.worldguard.bukkit.commands;
|
||||
|
||||
import com.google.common.base.Function;
|
||||
import com.google.common.util.concurrent.FutureCallback;
|
||||
import com.google.common.util.concurrent.Futures;
|
||||
import com.google.common.util.concurrent.ListenableFuture;
|
||||
import com.sk89q.worldguard.bukkit.WorldGuardPlugin;
|
||||
import com.sk89q.worldguard.util.paste.EngineHubPaste;
|
||||
import org.bukkit.ChatColor;
|
||||
import org.bukkit.command.BlockCommandSender;
|
||||
import org.bukkit.command.CommandSender;
|
||||
@@ -27,12 +32,17 @@ import org.bukkit.command.ConsoleCommandSender;
|
||||
import org.bukkit.entity.Player;
|
||||
|
||||
import javax.annotation.Nullable;
|
||||
import java.net.URL;
|
||||
import java.util.logging.Level;
|
||||
import java.util.logging.Logger;
|
||||
|
||||
/**
|
||||
* Command-related utility methods.
|
||||
*/
|
||||
public final class CommandUtils {
|
||||
|
||||
private static final Logger log = Logger.getLogger(CommandUtils.class.getCanonicalName());
|
||||
|
||||
private CommandUtils() {
|
||||
}
|
||||
|
||||
@@ -110,6 +120,7 @@ public final class CommandUtils {
|
||||
str = str.replace("&o", ChatColor.ITALIC.toString());
|
||||
|
||||
str = str.replace("&x", ChatColor.RESET.toString());
|
||||
str = str.replace("&r", ChatColor.RESET.toString());
|
||||
|
||||
return str;
|
||||
}
|
||||
@@ -152,4 +163,34 @@ public final class CommandUtils {
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
* Submit data to a pastebin service and inform the sender of
|
||||
* success or failure.
|
||||
*
|
||||
* @param plugin The plugin
|
||||
* @param sender The sender
|
||||
* @param content The content
|
||||
* @param successMessage The message, formatted with {@link String#format(String, Object...)} on success
|
||||
*/
|
||||
public static void pastebin(WorldGuardPlugin plugin, final CommandSender sender, String content, final String successMessage) {
|
||||
ListenableFuture<URL> future = new EngineHubPaste().paste(content);
|
||||
|
||||
AsyncCommandHelper.wrap(future, plugin, sender)
|
||||
.registerWithSupervisor("Submitting content to a pastebin service...")
|
||||
.sendMessageAfterDelay("(Please wait... sending output to pastebin...)");
|
||||
|
||||
Futures.addCallback(future, new FutureCallback<URL>() {
|
||||
@Override
|
||||
public void onSuccess(URL url) {
|
||||
sender.sendMessage(ChatColor.YELLOW + String.format(successMessage, url));
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onFailure(Throwable throwable) {
|
||||
log.log(Level.WARNING, "Failed to submit pastebin", throwable);
|
||||
sender.sendMessage(ChatColor.RED + "Failed to submit to a pastebin. Please see console for the error.");
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
}
|
||||
@@ -19,10 +19,7 @@
|
||||
|
||||
package com.sk89q.worldguard.bukkit.commands;
|
||||
|
||||
import com.sk89q.minecraft.util.commands.Command;
|
||||
import com.sk89q.minecraft.util.commands.CommandContext;
|
||||
import com.sk89q.minecraft.util.commands.CommandException;
|
||||
import com.sk89q.minecraft.util.commands.CommandPermissions;
|
||||
import com.sk89q.minecraft.util.commands.*;
|
||||
import com.sk89q.worldguard.bukkit.WorldGuardPlugin;
|
||||
import com.sk89q.worldguard.bukkit.event.debug.*;
|
||||
import com.sk89q.worldguard.util.report.CancelReport;
|
||||
@@ -58,45 +55,45 @@ public class DebuggingCommands {
|
||||
this.plugin = plugin;
|
||||
}
|
||||
|
||||
@Command(aliases = {"testbreak"}, usage = "[player]", desc = "Simulate a block break", min = 1, max = 1, flags = "t")
|
||||
@Command(aliases = {"testbreak"}, usage = "[player]", desc = "Simulate a block break", min = 1, max = 1, flags = "ts")
|
||||
@CommandPermissions("worldguard.debug.event")
|
||||
public void fireBreakEvent(CommandContext args, final CommandSender sender) throws CommandException {
|
||||
Player target = plugin.matchSinglePlayer(sender, args.getString(0));
|
||||
Block block = traceBlock(sender, target, args.hasFlag('t'));
|
||||
sender.sendMessage(ChatColor.AQUA + "Testing BLOCK BREAK at " + ChatColor.DARK_AQUA + block);
|
||||
LoggingBlockBreakEvent event = new LoggingBlockBreakEvent(block, target);
|
||||
testEvent(sender, target, event);
|
||||
testEvent(sender, target, event, args.hasFlag('s'));
|
||||
}
|
||||
|
||||
|
||||
@Command(aliases = {"testplace"}, usage = "[player]", desc = "Simulate a block place", min = 1, max = 1, flags = "t")
|
||||
@Command(aliases = {"testplace"}, usage = "[player]", desc = "Simulate a block place", min = 1, max = 1, flags = "ts")
|
||||
@CommandPermissions("worldguard.debug.event")
|
||||
public void firePlaceEvent(CommandContext args, final CommandSender sender) throws CommandException {
|
||||
Player target = plugin.matchSinglePlayer(sender, args.getString(0));
|
||||
Block block = traceBlock(sender, target, args.hasFlag('t'));
|
||||
sender.sendMessage(ChatColor.AQUA + "Testing BLOCK PLACE at " + ChatColor.DARK_AQUA + block);
|
||||
LoggingBlockPlaceEvent event = new LoggingBlockPlaceEvent(block, block.getState(), block.getRelative(BlockFace.DOWN), target.getItemInHand(), target, true);
|
||||
testEvent(sender, target, event);
|
||||
testEvent(sender, target, event, args.hasFlag('s'));
|
||||
}
|
||||
|
||||
@Command(aliases = {"testinteract"}, usage = "[player]", desc = "Simulate a block interact", min = 1, max = 1, flags = "t")
|
||||
@Command(aliases = {"testinteract"}, usage = "[player]", desc = "Simulate a block interact", min = 1, max = 1, flags = "ts")
|
||||
@CommandPermissions("worldguard.debug.event")
|
||||
public void fireInteractEvent(CommandContext args, final CommandSender sender) throws CommandException {
|
||||
Player target = plugin.matchSinglePlayer(sender, args.getString(0));
|
||||
Block block = traceBlock(sender, target, args.hasFlag('t'));
|
||||
sender.sendMessage(ChatColor.AQUA + "Testing BLOCK INTERACT at " + ChatColor.DARK_AQUA + block);
|
||||
LoggingPlayerInteractEvent event = new LoggingPlayerInteractEvent(target, Action.RIGHT_CLICK_BLOCK, target.getItemInHand(), block, BlockFace.SOUTH);
|
||||
testEvent(sender, target, event);
|
||||
testEvent(sender, target, event, args.hasFlag('s'));
|
||||
}
|
||||
|
||||
@Command(aliases = {"testdamage"}, usage = "[player]", desc = "Simulate an entity damage", min = 1, max = 1, flags = "t")
|
||||
@Command(aliases = {"testdamage"}, usage = "[player]", desc = "Simulate an entity damage", min = 1, max = 1, flags = "ts")
|
||||
@CommandPermissions("worldguard.debug.event")
|
||||
public void fireDamageEvent(CommandContext args, final CommandSender sender) throws CommandException {
|
||||
Player target = plugin.matchSinglePlayer(sender, args.getString(0));
|
||||
Entity entity = traceEntity(sender, target, args.hasFlag('t'));
|
||||
sender.sendMessage(ChatColor.AQUA + "Testing ENTITY DAMAGE on " + ChatColor.DARK_AQUA + entity);
|
||||
LoggingEntityDamageByEntityEvent event = new LoggingEntityDamageByEntityEvent(target, entity, DamageCause.ENTITY_ATTACK, 1);
|
||||
testEvent(sender, target, event);
|
||||
testEvent(sender, target, event, args.hasFlag('s'));
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -104,10 +101,11 @@ public class DebuggingCommands {
|
||||
*
|
||||
* @param receiver The receiver of the messages
|
||||
* @param target The target
|
||||
* @param event THe event
|
||||
* @param event The event
|
||||
* @param stacktraceMode Whether stack traces should be generated and posted
|
||||
* @param <T> The type of event
|
||||
*/
|
||||
private <T extends Event & CancelLogging> void testEvent(CommandSender receiver, Player target, T event) {
|
||||
private <T extends Event & CancelLogging> void testEvent(CommandSender receiver, Player target, T event, boolean stacktraceMode) throws CommandPermissionsException {
|
||||
boolean isConsole = receiver instanceof ConsoleCommandSender;
|
||||
|
||||
if (!receiver.equals(target)) {
|
||||
@@ -122,12 +120,22 @@ public class DebuggingCommands {
|
||||
Bukkit.getPluginManager().callEvent(event);
|
||||
int start = new Exception().getStackTrace().length;
|
||||
CancelReport report = new CancelReport(event, event.getCancels(), start);
|
||||
report.setDetectingPlugin(!stacktraceMode);
|
||||
String result = report.toString();
|
||||
receiver.sendMessage(result.replaceAll("(?m)^", ChatColor.AQUA.toString()));
|
||||
|
||||
if (result.length() >= 500 && !isConsole) {
|
||||
receiver.sendMessage(ChatColor.GRAY + "The report was also printed to console.");
|
||||
if (stacktraceMode) {
|
||||
receiver.sendMessage(ChatColor.GRAY + "The report was printed to console.");
|
||||
log.info("Event report for " + receiver.getName() + ":\n\n" + result);
|
||||
|
||||
plugin.checkPermission(receiver, "worldguard.debug.pastebin");
|
||||
CommandUtils.pastebin(plugin, receiver, result, "Event debugging report: %s.txt");
|
||||
} else {
|
||||
receiver.sendMessage(result.replaceAll("(?m)^", ChatColor.AQUA.toString()));
|
||||
|
||||
if (result.length() >= 500 && !isConsole) {
|
||||
receiver.sendMessage(ChatColor.GRAY + "The report was also printed to console.");
|
||||
log.info("Event report for " + receiver.getName() + ":\n\n" + result);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -19,11 +19,6 @@
|
||||
|
||||
package com.sk89q.worldguard.bukkit.commands;
|
||||
|
||||
import org.bukkit.ChatColor;
|
||||
import org.bukkit.command.CommandSender;
|
||||
import org.bukkit.entity.Player;
|
||||
import org.bukkit.inventory.ItemStack;
|
||||
|
||||
import com.sk89q.minecraft.util.commands.Command;
|
||||
import com.sk89q.minecraft.util.commands.CommandContext;
|
||||
import com.sk89q.minecraft.util.commands.CommandException;
|
||||
@@ -31,6 +26,12 @@ import com.sk89q.minecraft.util.commands.CommandPermissions;
|
||||
import com.sk89q.worldedit.blocks.ItemType;
|
||||
import com.sk89q.worldguard.bukkit.ConfigurationManager;
|
||||
import com.sk89q.worldguard.bukkit.WorldGuardPlugin;
|
||||
import com.sk89q.worldguard.session.Session;
|
||||
import com.sk89q.worldguard.session.handler.GodMode;
|
||||
import org.bukkit.ChatColor;
|
||||
import org.bukkit.command.CommandSender;
|
||||
import org.bukkit.entity.Player;
|
||||
import org.bukkit.inventory.ItemStack;
|
||||
|
||||
public class GeneralCommands {
|
||||
private final WorldGuardPlugin plugin;
|
||||
@@ -54,7 +55,7 @@ public class GeneralCommands {
|
||||
|
||||
// Check permissions!
|
||||
plugin.checkPermission(sender, "worldguard.god");
|
||||
} else if (args.argsLength() == 1) {
|
||||
} else {
|
||||
targets = plugin.matchPlayers(sender, args.getString(0));
|
||||
|
||||
// Check permissions!
|
||||
@@ -62,26 +63,29 @@ public class GeneralCommands {
|
||||
}
|
||||
|
||||
for (Player player : targets) {
|
||||
config.enableGodMode(player);
|
||||
player.setFireTicks(0);
|
||||
|
||||
// Tell the user
|
||||
if (player.equals(sender)) {
|
||||
player.sendMessage(ChatColor.YELLOW + "God mode enabled! Use /ungod to disable.");
|
||||
|
||||
// Keep track of this
|
||||
included = true;
|
||||
} else {
|
||||
player.sendMessage(ChatColor.YELLOW + "God enabled by "
|
||||
+ plugin.toName(sender) + ".");
|
||||
|
||||
Session session = plugin.getSessionManager().get(player);
|
||||
|
||||
if (GodMode.set(player, session, true)) {
|
||||
player.setFireTicks(0);
|
||||
|
||||
// Tell the user
|
||||
if (player.equals(sender)) {
|
||||
player.sendMessage(ChatColor.YELLOW + "God mode enabled! Use /ungod to disable.");
|
||||
|
||||
// Keep track of this
|
||||
included = true;
|
||||
} else {
|
||||
player.sendMessage(ChatColor.YELLOW + "God enabled by "
|
||||
+ plugin.toName(sender) + ".");
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// The player didn't receive any items, then we need to send the
|
||||
// user a message so s/he know that something is indeed working
|
||||
if (!included && args.hasFlag('s')) {
|
||||
sender.sendMessage(ChatColor.YELLOW.toString() + "Players now have god mode.");
|
||||
sender.sendMessage(ChatColor.YELLOW + "Players now have god mode.");
|
||||
}
|
||||
}
|
||||
|
||||
@@ -100,7 +104,7 @@ public class GeneralCommands {
|
||||
|
||||
// Check permissions!
|
||||
plugin.checkPermission(sender, "worldguard.god");
|
||||
} else if (args.argsLength() == 1) {
|
||||
} else {
|
||||
targets = plugin.matchPlayers(sender, args.getString(0));
|
||||
|
||||
// Check permissions!
|
||||
@@ -108,25 +112,27 @@ public class GeneralCommands {
|
||||
}
|
||||
|
||||
for (Player player : targets) {
|
||||
config.disableGodMode(player);
|
||||
|
||||
// Tell the user
|
||||
if (player.equals(sender)) {
|
||||
player.sendMessage(ChatColor.YELLOW + "God mode disabled!");
|
||||
|
||||
// Keep track of this
|
||||
included = true;
|
||||
} else {
|
||||
player.sendMessage(ChatColor.YELLOW + "God disabled by "
|
||||
+ plugin.toName(sender) + ".");
|
||||
|
||||
Session session = plugin.getSessionManager().get(player);
|
||||
|
||||
if (GodMode.set(player, session, false)) {
|
||||
// Tell the user
|
||||
if (player.equals(sender)) {
|
||||
player.sendMessage(ChatColor.YELLOW + "God mode disabled!");
|
||||
|
||||
// Keep track of this
|
||||
included = true;
|
||||
} else {
|
||||
player.sendMessage(ChatColor.YELLOW + "God disabled by "
|
||||
+ plugin.toName(sender) + ".");
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// The player didn't receive any items, then we need to send the
|
||||
// user a message so s/he know that something is indeed working
|
||||
if (!included && args.hasFlag('s')) {
|
||||
sender.sendMessage(ChatColor.YELLOW.toString() + "Players no longer have god mode.");
|
||||
sender.sendMessage(ChatColor.YELLOW + "Players no longer have god mode.");
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -19,15 +19,21 @@
|
||||
|
||||
package com.sk89q.worldguard.bukkit.commands;
|
||||
|
||||
import com.google.common.base.Predicate;
|
||||
import com.google.common.base.Predicates;
|
||||
import com.google.common.io.Files;
|
||||
import com.google.common.util.concurrent.FutureCallback;
|
||||
import com.google.common.util.concurrent.Futures;
|
||||
import com.google.common.util.concurrent.MoreExecutors;
|
||||
import com.sk89q.minecraft.util.commands.*;
|
||||
import com.sk89q.worldguard.bukkit.ConfigurationManager;
|
||||
import com.sk89q.worldguard.bukkit.WorldGuardPlugin;
|
||||
import com.sk89q.worldguard.bukkit.util.logging.LoggerToChatHandler;
|
||||
import com.sk89q.worldguard.bukkit.util.report.*;
|
||||
import com.sk89q.worldguard.util.paste.Pastebin;
|
||||
import com.sk89q.worldguard.util.profiler.SamplerBuilder;
|
||||
import com.sk89q.worldguard.util.profiler.SamplerBuilder.Sampler;
|
||||
import com.sk89q.worldguard.util.profiler.ThreadIdFilter;
|
||||
import com.sk89q.worldguard.util.profiler.ThreadNameFilter;
|
||||
import com.sk89q.worldguard.util.report.ReportList;
|
||||
import com.sk89q.worldguard.util.report.SystemInfoReport;
|
||||
import com.sk89q.worldguard.util.task.Task;
|
||||
@@ -38,12 +44,14 @@ import org.bukkit.World;
|
||||
import org.bukkit.command.CommandSender;
|
||||
import org.bukkit.entity.Player;
|
||||
|
||||
import javax.annotation.Nullable;
|
||||
import java.io.File;
|
||||
import java.io.IOException;
|
||||
import java.net.URL;
|
||||
import java.lang.management.ThreadInfo;
|
||||
import java.nio.charset.Charset;
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
import java.util.logging.Level;
|
||||
import java.util.logging.Logger;
|
||||
|
||||
@@ -52,6 +60,8 @@ public class WorldGuardCommands {
|
||||
private static final Logger log = Logger.getLogger(WorldGuardCommands.class.getCanonicalName());
|
||||
|
||||
private final WorldGuardPlugin plugin;
|
||||
@Nullable
|
||||
private Sampler activeSampler;
|
||||
|
||||
public WorldGuardCommands(WorldGuardPlugin plugin) {
|
||||
this.plugin = plugin;
|
||||
@@ -128,23 +138,111 @@ public class WorldGuardCommands {
|
||||
|
||||
if (args.hasFlag('p')) {
|
||||
plugin.checkPermission(sender, "worldguard.report.pastebin");
|
||||
|
||||
sender.sendMessage(ChatColor.YELLOW + "Now uploading to Pastebin...");
|
||||
CommandUtils.pastebin(plugin, sender, result, "WorldGuard report: %s.report");
|
||||
}
|
||||
}
|
||||
|
||||
Futures.addCallback(new Pastebin().paste(result), new FutureCallback<URL>() {
|
||||
@Override
|
||||
public void onSuccess(URL url) {
|
||||
sender.sendMessage(ChatColor.YELLOW + "WorldGuard report: " + url);
|
||||
}
|
||||
@Command(aliases = {"profile"}, usage = "[<minutes>]",
|
||||
desc = "Profile the CPU usage of the server", min = 0, max = 1,
|
||||
flags = "t:p")
|
||||
@CommandPermissions("worldguard.profile")
|
||||
public void profile(final CommandContext args, final CommandSender sender) throws CommandException {
|
||||
Predicate<ThreadInfo> threadFilter;
|
||||
String threadName = args.getFlag('t');
|
||||
final boolean pastebin;
|
||||
|
||||
@Override
|
||||
public void onFailure(Throwable throwable) {
|
||||
log.log(Level.WARNING, "Failed to submit pastebin", throwable);
|
||||
sender.sendMessage(ChatColor.RED + "The WorldGuard report could not be saved to a pastebin service. Please see console for the error.");
|
||||
}
|
||||
});
|
||||
if (args.hasFlag('p')) {
|
||||
plugin.checkPermission(sender, "worldguard.report.pastebin");
|
||||
pastebin = true;
|
||||
} else {
|
||||
pastebin = false;
|
||||
}
|
||||
|
||||
if (threadName == null) {
|
||||
threadFilter = new ThreadIdFilter(Thread.currentThread().getId());
|
||||
} else if (threadName.equals("*")) {
|
||||
threadFilter = Predicates.alwaysTrue();
|
||||
} else {
|
||||
threadFilter = new ThreadNameFilter(threadName);
|
||||
}
|
||||
|
||||
int minutes;
|
||||
if (args.argsLength() == 0) {
|
||||
minutes = 5;
|
||||
} else {
|
||||
minutes = args.getInteger(0);
|
||||
if (minutes < 1) {
|
||||
throw new CommandException("You must run the profile for at least 1 minute.");
|
||||
} else if (minutes > 10) {
|
||||
throw new CommandException("You can profile for, at maximum, 10 minutes.");
|
||||
}
|
||||
}
|
||||
|
||||
Sampler sampler;
|
||||
|
||||
synchronized (this) {
|
||||
if (activeSampler != null) {
|
||||
throw new CommandException("A profile is currently in progress! Please use /wg stopprofile to stop the current profile.");
|
||||
}
|
||||
|
||||
SamplerBuilder builder = new SamplerBuilder();
|
||||
builder.setThreadFilter(threadFilter);
|
||||
builder.setRunTime(minutes, TimeUnit.MINUTES);
|
||||
sampler = activeSampler = builder.start();
|
||||
}
|
||||
|
||||
AsyncCommandHelper.wrap(sampler.getFuture(), plugin, sender)
|
||||
.formatUsing(minutes)
|
||||
.registerWithSupervisor("Running CPU profiler for %d minute(s)...")
|
||||
.sendMessageAfterDelay("(Please wait... profiling for %d minute(s)...)")
|
||||
.thenTellErrorsOnly("CPU profiling failed.");
|
||||
|
||||
sampler.getFuture().addListener(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
synchronized (WorldGuardCommands.this) {
|
||||
activeSampler = null;
|
||||
}
|
||||
}
|
||||
}, MoreExecutors.sameThreadExecutor());
|
||||
|
||||
Futures.addCallback(sampler.getFuture(), new FutureCallback<Sampler>() {
|
||||
@Override
|
||||
public void onSuccess(Sampler result) {
|
||||
String output = result.toString();
|
||||
|
||||
try {
|
||||
File dest = new File(plugin.getDataFolder(), "profile.txt");
|
||||
Files.write(output, dest, Charset.forName("UTF-8"));
|
||||
sender.sendMessage(ChatColor.YELLOW + "CPU profiling data written to " + dest.getAbsolutePath());
|
||||
} catch (IOException e) {
|
||||
sender.sendMessage(ChatColor.RED + "Failed to write CPU profiling data: " + e.getMessage());
|
||||
}
|
||||
|
||||
if (pastebin) {
|
||||
CommandUtils.pastebin(plugin, sender, output, "Profile result: %s.profile");
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onFailure(Throwable throwable) {
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
@Command(aliases = {"stopprofile"}, usage = "",desc = "Stop a running profile", min = 0, max = 0)
|
||||
@CommandPermissions("worldguard.profile")
|
||||
public void stopProfile(CommandContext args, final CommandSender sender) throws CommandException {
|
||||
synchronized (this) {
|
||||
if (activeSampler == null) {
|
||||
throw new CommandException("No CPU profile is currently running.");
|
||||
}
|
||||
|
||||
activeSampler.cancel();
|
||||
activeSampler = null;
|
||||
}
|
||||
|
||||
sender.sendMessage("The running CPU profile has been stopped.");
|
||||
}
|
||||
|
||||
@Command(aliases = {"flushstates", "clearstates"},
|
||||
@@ -152,12 +250,12 @@ public class WorldGuardCommands {
|
||||
@CommandPermissions("worldguard.flushstates")
|
||||
public void flushStates(CommandContext args, CommandSender sender) throws CommandException {
|
||||
if (args.argsLength() == 0) {
|
||||
plugin.getFlagStateManager().forgetAll();
|
||||
plugin.getSessionManager().resetAllStates();
|
||||
sender.sendMessage("Cleared all states.");
|
||||
} else {
|
||||
Player player = plugin.getServer().getPlayer(args.getString(0));
|
||||
if (player != null) {
|
||||
plugin.getFlagStateManager().forget(player);
|
||||
plugin.getSessionManager().resetState(player);
|
||||
sender.sendMessage("Cleared states for player \"" + player.getName() + "\".");
|
||||
}
|
||||
}
|
||||
|
||||
@@ -519,7 +519,7 @@ public final class RegionCommands extends RegionCommandsBase {
|
||||
// Also make sure that we can use this flag
|
||||
// This permission is confusing and probably should be replaced, but
|
||||
// but not here -- in the model
|
||||
if (!permModel.maySetFlag(existing, foundFlag)) {
|
||||
if (!permModel.maySetFlag(existing, foundFlag, value)) {
|
||||
throw new CommandPermissionsException();
|
||||
}
|
||||
|
||||
|
||||
@@ -19,20 +19,21 @@
|
||||
|
||||
package com.sk89q.worldguard.bukkit.event;
|
||||
|
||||
import org.bukkit.event.Event.Result;
|
||||
|
||||
/**
|
||||
* A bulk event contains several affected objects in a list.
|
||||
*/
|
||||
public interface BulkEvent {
|
||||
|
||||
/**
|
||||
* Return whether the event is explicitly cancelled.
|
||||
* Get the actual result.
|
||||
*
|
||||
* <p>By default, bulk events will cancel itself if the number of affected
|
||||
* objects drops to zero. This method returns the true cancellation
|
||||
* status.</p>
|
||||
* <p>By default, bulk events will set the result to DENY if the number of
|
||||
* affected objects drops to zero. This method returns the true result.</p>
|
||||
*
|
||||
* @return true if really cancelled
|
||||
* @return the explicit result
|
||||
*/
|
||||
boolean isExplicitlyCancelled();
|
||||
Result getExplicitResult();
|
||||
|
||||
}
|
||||
@@ -34,13 +34,13 @@ import static com.google.common.base.Preconditions.checkNotNull;
|
||||
* This event is an internal event. We do not recommend handling or throwing
|
||||
* this event or its subclasses as the interface is highly subject to change.
|
||||
*/
|
||||
public abstract class DelegateEvent extends Event implements Cancellable {
|
||||
public abstract class DelegateEvent extends Event implements Cancellable, Handleable {
|
||||
|
||||
@Nullable
|
||||
private final Event originalEvent;
|
||||
private final Cause cause;
|
||||
private final List<StateFlag> relevantFlags = Lists.newArrayList();
|
||||
private boolean cancelled;
|
||||
private Result result = Result.DEFAULT;
|
||||
private boolean silent;
|
||||
|
||||
/**
|
||||
@@ -85,12 +85,24 @@ public abstract class DelegateEvent extends Event implements Cancellable {
|
||||
|
||||
@Override
|
||||
public boolean isCancelled() {
|
||||
return cancelled;
|
||||
return getResult() == Result.DENY;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setCancelled(boolean cancel) {
|
||||
this.cancelled = cancel;
|
||||
if (cancel) {
|
||||
setResult(Result.DENY);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public Result getResult() {
|
||||
return result;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setResult(Result result) {
|
||||
this.result = result;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -106,9 +118,25 @@ public abstract class DelegateEvent extends Event implements Cancellable {
|
||||
* Set whether this should be a silent check.
|
||||
*
|
||||
* @param silent true if silent
|
||||
* @return the same event
|
||||
*/
|
||||
void setSilent(boolean silent) {
|
||||
public DelegateEvent setSilent(boolean silent) {
|
||||
this.silent = silent;
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the event to {@link Result#ALLOW} if {@code allowed} is true.
|
||||
*
|
||||
* @param allowed true to set the result
|
||||
* @return the same event
|
||||
*/
|
||||
public DelegateEvent setAllowed(boolean allowed) {
|
||||
if (allowed) {
|
||||
setResult(Result.ALLOW);
|
||||
}
|
||||
|
||||
return this;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -19,6 +19,8 @@
|
||||
|
||||
package com.sk89q.worldguard.bukkit.event;
|
||||
|
||||
import org.bukkit.event.Event.Result;
|
||||
|
||||
/**
|
||||
* Utility methods for dealing with delegate events.
|
||||
*/
|
||||
@@ -52,4 +54,19 @@ public final class DelegateEvents {
|
||||
return event;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set an event as handled as {@link Result#ALLOW} if {@code allowed} is
|
||||
* true, otherwise do nothing.
|
||||
*
|
||||
* @param event the event
|
||||
* @param <T> the type of event
|
||||
* @return the same event
|
||||
*/
|
||||
public static <T extends Handleable> T setAllowed(T event, boolean allowed) {
|
||||
if (allowed) {
|
||||
event.setResult(Result.ALLOW);
|
||||
}
|
||||
return event;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,30 @@
|
||||
/*
|
||||
* WorldGuard, a suite of tools for Minecraft
|
||||
* Copyright (C) sk89q <http://www.sk89q.com>
|
||||
* Copyright (C) WorldGuard team and contributors
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify it
|
||||
* under the terms of the GNU Lesser General Public License as published by the
|
||||
* Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License
|
||||
* for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
package com.sk89q.worldguard.bukkit.event;
|
||||
|
||||
import org.bukkit.event.Event.Result;
|
||||
|
||||
public interface Handleable {
|
||||
|
||||
Result getResult();
|
||||
|
||||
void setResult(Result result);
|
||||
|
||||
}
|
||||
@@ -70,16 +70,6 @@ abstract class AbstractBlockEvent extends DelegateEvent implements BulkEvent {
|
||||
return blocks;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isCancelled() {
|
||||
return super.isCancelled() || blocks.isEmpty();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isExplicitlyCancelled() {
|
||||
return super.isCancelled();
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the world.
|
||||
*
|
||||
@@ -153,4 +143,18 @@ abstract class AbstractBlockEvent extends DelegateEvent implements BulkEvent {
|
||||
public Material getEffectiveMaterial() {
|
||||
return effectiveMaterial;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Result getResult() {
|
||||
if (blocks.isEmpty()) {
|
||||
return Result.DENY;
|
||||
}
|
||||
return super.getResult();
|
||||
}
|
||||
|
||||
@Override
|
||||
public Result getExplicitResult() {
|
||||
return super.getResult();
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1,88 +0,0 @@
|
||||
/*
|
||||
* WorldGuard, a suite of tools for Minecraft
|
||||
* Copyright (C) sk89q <http://www.sk89q.com>
|
||||
* Copyright (C) WorldGuard team and contributors
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify it
|
||||
* under the terms of the GNU Lesser General Public License as published by the
|
||||
* Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License
|
||||
* for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
package com.sk89q.worldguard.bukkit.internal;
|
||||
|
||||
import com.sk89q.worldguard.bukkit.WorldGuardPlugin;
|
||||
import com.sk89q.worldguard.bukkit.listener.FlagStateManager;
|
||||
import org.bukkit.Location;
|
||||
import org.bukkit.World;
|
||||
import org.bukkit.entity.Player;
|
||||
|
||||
import com.sk89q.worldedit.Vector;
|
||||
import com.sk89q.worldguard.protection.ApplicableRegionSet;
|
||||
import com.sk89q.worldguard.protection.flags.DefaultFlag;
|
||||
import com.sk89q.worldguard.protection.flags.StateFlag;
|
||||
import com.sk89q.worldguard.protection.managers.RegionManager;
|
||||
|
||||
public final class RegionQueryUtil {
|
||||
|
||||
private RegionQueryUtil() {
|
||||
}
|
||||
|
||||
public static boolean isInvincible(WorldGuardPlugin plugin, Player player) {
|
||||
return isInvincible(plugin, player, null);
|
||||
}
|
||||
|
||||
public static boolean isInvincible(WorldGuardPlugin plugin, Player player,
|
||||
ApplicableRegionSet set) {
|
||||
Location loc = player.getLocation();
|
||||
World world = player.getWorld();
|
||||
|
||||
FlagStateManager.PlayerFlagState state = plugin.getFlagStateManager().getState(player);
|
||||
|
||||
if (state.lastInvincibleWorld == null ||
|
||||
!state.lastInvincibleWorld.equals(world) ||
|
||||
state.lastInvincibleX != loc.getBlockX() ||
|
||||
state.lastInvincibleY != loc.getBlockY() ||
|
||||
state.lastInvincibleZ != loc.getBlockZ()) {
|
||||
state.lastInvincibleX = loc.getBlockX();
|
||||
state.lastInvincibleY = loc.getBlockY();
|
||||
state.lastInvincibleZ = loc.getBlockZ();
|
||||
state.lastInvincibleWorld = world;
|
||||
|
||||
if (set == null) {
|
||||
Vector vec = new Vector(state.lastInvincibleX,
|
||||
state.lastInvincibleY, state.lastInvincibleZ);
|
||||
RegionManager mgr = plugin.getGlobalRegionManager().get(world);
|
||||
set = mgr.getApplicableRegions(vec);
|
||||
}
|
||||
|
||||
state.wasInvincible = set.allows(DefaultFlag.INVINCIBILITY, plugin.wrapPlayer(player));
|
||||
}
|
||||
|
||||
return state.wasInvincible;
|
||||
}
|
||||
|
||||
public static Boolean isAllowedInvinciblity(WorldGuardPlugin plugin, Player player) {
|
||||
World world = player.getWorld();
|
||||
FlagStateManager.PlayerFlagState state = plugin.getFlagStateManager().getState(player);
|
||||
Vector vec = new Vector(state.lastInvincibleX, state.lastInvincibleY, state.lastInvincibleZ);
|
||||
|
||||
StateFlag.State regionState = plugin.getGlobalRegionManager().get(world).
|
||||
getApplicableRegions(vec).getFlag(DefaultFlag.INVINCIBILITY, plugin.wrapPlayer(player));
|
||||
if (regionState == StateFlag.State.ALLOW) {
|
||||
return Boolean.TRUE;
|
||||
} else if (regionState == StateFlag.State.DENY) {
|
||||
return Boolean.FALSE;
|
||||
} else {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -70,4 +70,9 @@ public class TargetMatcherSet {
|
||||
return test(new MaterialTarget(itemStack.getTypeId(), itemStack.getDurability()));
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return entries.toString();
|
||||
}
|
||||
|
||||
}
|
||||
@@ -21,14 +21,7 @@ package com.sk89q.worldguard.bukkit.listener;
|
||||
|
||||
import com.google.common.base.Predicate;
|
||||
import com.sk89q.worldguard.LocalPlayer;
|
||||
import com.sk89q.worldguard.blacklist.event.BlockBreakBlacklistEvent;
|
||||
import com.sk89q.worldguard.blacklist.event.BlockDispenseBlacklistEvent;
|
||||
import com.sk89q.worldguard.blacklist.event.BlockInteractBlacklistEvent;
|
||||
import com.sk89q.worldguard.blacklist.event.BlockPlaceBlacklistEvent;
|
||||
import com.sk89q.worldguard.blacklist.event.ItemAcquireBlacklistEvent;
|
||||
import com.sk89q.worldguard.blacklist.event.ItemDestroyWithBlacklistEvent;
|
||||
import com.sk89q.worldguard.blacklist.event.ItemDropBlacklistEvent;
|
||||
import com.sk89q.worldguard.blacklist.event.ItemUseBlacklistEvent;
|
||||
import com.sk89q.worldguard.blacklist.event.*;
|
||||
import com.sk89q.worldguard.bukkit.ConfigurationManager;
|
||||
import com.sk89q.worldguard.bukkit.WorldConfiguration;
|
||||
import com.sk89q.worldguard.bukkit.WorldGuardPlugin;
|
||||
@@ -42,11 +35,16 @@ import com.sk89q.worldguard.bukkit.util.Materials;
|
||||
import org.bukkit.Location;
|
||||
import org.bukkit.Material;
|
||||
import org.bukkit.entity.Entity;
|
||||
import org.bukkit.entity.HumanEntity;
|
||||
import org.bukkit.entity.Item;
|
||||
import org.bukkit.entity.Player;
|
||||
import org.bukkit.event.EventHandler;
|
||||
import org.bukkit.event.block.BlockDispenseEvent;
|
||||
import org.bukkit.event.inventory.InventoryClickEvent;
|
||||
import org.bukkit.event.inventory.InventoryCreativeEvent;
|
||||
import org.bukkit.event.player.PlayerDropItemEvent;
|
||||
import org.bukkit.event.player.PlayerItemHeldEvent;
|
||||
import org.bukkit.inventory.Inventory;
|
||||
import org.bukkit.inventory.ItemStack;
|
||||
|
||||
import static com.sk89q.worldguard.bukkit.BukkitUtil.createTarget;
|
||||
@@ -259,4 +257,64 @@ public class BlacklistListener extends AbstractListener {
|
||||
}
|
||||
}
|
||||
|
||||
@EventHandler(ignoreCancelled = true)
|
||||
public void onInventoryClick(InventoryClickEvent event) {
|
||||
HumanEntity entity = event.getWhoClicked();
|
||||
Inventory inventory = event.getInventory();
|
||||
ItemStack item = event.getCurrentItem();
|
||||
|
||||
if (item != null && entity instanceof Player) {
|
||||
Player player = (Player) entity;
|
||||
ConfigurationManager cfg = getPlugin().getGlobalStateManager();
|
||||
WorldConfiguration wcfg = cfg.get(entity.getWorld());
|
||||
LocalPlayer localPlayer = getPlugin().wrapPlayer(player);
|
||||
|
||||
if (wcfg.getBlacklist() != null && !wcfg.getBlacklist().check(
|
||||
new ItemAcquireBlacklistEvent(localPlayer, toVector(entity.getLocation()), createTarget(item)), false, false)) {
|
||||
event.setCancelled(true);
|
||||
|
||||
if (inventory.getHolder().equals(player)) {
|
||||
event.setCurrentItem(null);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@EventHandler(ignoreCancelled = true)
|
||||
public void onInventoryCreative(InventoryCreativeEvent event) {
|
||||
HumanEntity entity = event.getWhoClicked();
|
||||
ItemStack item = event.getCursor();
|
||||
|
||||
if (item != null && entity instanceof Player) {
|
||||
Player player = (Player) entity;
|
||||
ConfigurationManager cfg = getPlugin().getGlobalStateManager();
|
||||
WorldConfiguration wcfg = cfg.get(entity.getWorld());
|
||||
LocalPlayer localPlayer = getPlugin().wrapPlayer(player);
|
||||
|
||||
if (wcfg.getBlacklist() != null && !wcfg.getBlacklist().check(
|
||||
new ItemAcquireBlacklistEvent(localPlayer, toVector(entity.getLocation()), createTarget(item)), false, false)) {
|
||||
event.setCancelled(true);
|
||||
event.setCursor(null);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@EventHandler(ignoreCancelled = true)
|
||||
public void onPlayerItemHeld(PlayerItemHeldEvent event) {
|
||||
Player player = event.getPlayer();
|
||||
Inventory inventory = player.getInventory();
|
||||
ItemStack item = inventory.getItem(event.getNewSlot());
|
||||
|
||||
if (item != null) {
|
||||
ConfigurationManager cfg = getPlugin().getGlobalStateManager();
|
||||
WorldConfiguration wcfg = cfg.get(player.getWorld());
|
||||
LocalPlayer localPlayer = getPlugin().wrapPlayer(player);
|
||||
|
||||
if (wcfg.getBlacklist() != null && !wcfg.getBlacklist().check(
|
||||
new ItemAcquireBlacklistEvent(localPlayer, toVector(player.getLocation()), createTarget(item)), false, false)) {
|
||||
inventory.setItem(event.getNewSlot(), null);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
@@ -193,8 +193,12 @@ public class BuildPermissionListener extends AbstractListener {
|
||||
Player player = (Player) rootCause;
|
||||
Material material = event.getItemStack().getType();
|
||||
|
||||
if (material.isBlock()) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (!hasBuildPermission(player, "item." + material.name().toLowerCase() + ".use")
|
||||
|| hasBuildPermission(player, "item.use." + material.name().toLowerCase())) {
|
||||
&& !hasBuildPermission(player, "item.use." + material.name().toLowerCase())) {
|
||||
tellErrorMessage(player, event.getWorld());
|
||||
event.setCancelled(true);
|
||||
}
|
||||
|
||||
@@ -30,6 +30,7 @@ import com.sk89q.worldguard.bukkit.event.inventory.UseItemEvent;
|
||||
import org.bukkit.Location;
|
||||
import org.bukkit.block.Block;
|
||||
import org.bukkit.event.Event;
|
||||
import org.bukkit.event.Event.Result;
|
||||
import org.bukkit.event.EventHandler;
|
||||
import org.bukkit.event.EventPriority;
|
||||
|
||||
@@ -67,8 +68,8 @@ public class DebuggingListener extends AbstractListener {
|
||||
builder.append("[").append(event.getCause()).append("]");
|
||||
builder.append(" ");
|
||||
builder.append(":").append(getEventName(event.getOriginalEvent()));
|
||||
if (event.isCancelled()) {
|
||||
builder.append(" [CANCELLED]");
|
||||
if (event.getResult() != Result.DEFAULT) {
|
||||
builder.append(" [").append(event.getResult()).append("]");
|
||||
}
|
||||
logger.info(builder.toString());
|
||||
}
|
||||
@@ -85,8 +86,8 @@ public class DebuggingListener extends AbstractListener {
|
||||
builder.append("@").append(toBlockString(event.getBlocks()));
|
||||
builder.append(" ");
|
||||
builder.append(":").append(getEventName(event.getOriginalEvent()));
|
||||
if (event.isCancelled()) {
|
||||
builder.append(" [CANCELLED]");
|
||||
if (event.getResult() != Result.DEFAULT) {
|
||||
builder.append(" [").append(event.getResult()).append("]");
|
||||
}
|
||||
logger.info(builder.toString());
|
||||
}
|
||||
@@ -103,8 +104,8 @@ public class DebuggingListener extends AbstractListener {
|
||||
builder.append("@").append(toBlockString(event.getBlocks()));
|
||||
builder.append(" ");
|
||||
builder.append(":").append(getEventName(event.getOriginalEvent()));
|
||||
if (event.isCancelled()) {
|
||||
builder.append(" [CANCELLED]");
|
||||
if (event.getResult() != Result.DEFAULT) {
|
||||
builder.append(" [").append(event.getResult()).append("]");
|
||||
}
|
||||
logger.info(builder.toString());
|
||||
}
|
||||
@@ -121,8 +122,8 @@ public class DebuggingListener extends AbstractListener {
|
||||
builder.append("@").append(toBlockString(event.getTarget()));
|
||||
builder.append(" ");
|
||||
builder.append(":").append(getEventName(event.getOriginalEvent()));
|
||||
if (event.isCancelled()) {
|
||||
builder.append(" [CANCELLED]");
|
||||
if (event.getResult() != Result.DEFAULT) {
|
||||
builder.append(" [").append(event.getResult()).append("]");
|
||||
}
|
||||
logger.info(builder.toString());
|
||||
}
|
||||
@@ -139,8 +140,8 @@ public class DebuggingListener extends AbstractListener {
|
||||
builder.append("@").append(toBlockString(event.getTarget()));
|
||||
builder.append(" ");
|
||||
builder.append(":").append(getEventName(event.getOriginalEvent()));
|
||||
if (event.isCancelled()) {
|
||||
builder.append(" [CANCELLED]");
|
||||
if (event.getResult() != Result.DEFAULT) {
|
||||
builder.append(" [").append(event.getResult()).append("]");
|
||||
}
|
||||
logger.info(builder.toString());
|
||||
}
|
||||
@@ -157,8 +158,8 @@ public class DebuggingListener extends AbstractListener {
|
||||
builder.append("@").append(toBlockString(event.getTarget()));
|
||||
builder.append(" ");
|
||||
builder.append(":").append(getEventName(event.getOriginalEvent()));
|
||||
if (event.isCancelled()) {
|
||||
builder.append(" [CANCELLED]");
|
||||
if (event.getResult() != Result.DEFAULT) {
|
||||
builder.append(" [").append(event.getResult()).append("]");
|
||||
}
|
||||
logger.info(builder.toString());
|
||||
}
|
||||
@@ -175,8 +176,8 @@ public class DebuggingListener extends AbstractListener {
|
||||
builder.append("@").append(event.getWorld().getName());
|
||||
builder.append(" ");
|
||||
builder.append(":").append(getEventName(event.getOriginalEvent()));
|
||||
if (event.isCancelled()) {
|
||||
builder.append(" [CANCELLED]");
|
||||
if (event.getResult() != Result.DEFAULT) {
|
||||
builder.append(" [").append(event.getResult()).append("]");
|
||||
}
|
||||
logger.info(builder.toString());
|
||||
}
|
||||
|
||||
@@ -24,7 +24,6 @@ import com.sk89q.worldguard.bukkit.WorldConfiguration;
|
||||
import com.sk89q.worldguard.bukkit.WorldGuardPlugin;
|
||||
import com.sk89q.worldguard.bukkit.cause.Cause;
|
||||
import com.sk89q.worldguard.bukkit.event.DelegateEvent;
|
||||
import com.sk89q.worldguard.bukkit.event.DelegateEvents;
|
||||
import com.sk89q.worldguard.bukkit.event.block.BreakBlockEvent;
|
||||
import com.sk89q.worldguard.bukkit.event.block.PlaceBlockEvent;
|
||||
import com.sk89q.worldguard.bukkit.event.block.UseBlockEvent;
|
||||
@@ -51,21 +50,22 @@ import org.bukkit.event.Cancellable;
|
||||
import org.bukkit.event.Event;
|
||||
import org.bukkit.event.Event.Result;
|
||||
import org.bukkit.event.EventHandler;
|
||||
import org.bukkit.event.Listener;
|
||||
import org.bukkit.event.block.*;
|
||||
import org.bukkit.event.entity.*;
|
||||
import org.bukkit.event.hanging.HangingBreakByEntityEvent;
|
||||
import org.bukkit.event.hanging.HangingBreakEvent;
|
||||
import org.bukkit.event.hanging.HangingPlaceEvent;
|
||||
import org.bukkit.event.inventory.InventoryMoveItemEvent;
|
||||
import org.bukkit.event.inventory.InventoryOpenEvent;
|
||||
import org.bukkit.event.player.*;
|
||||
import org.bukkit.event.vehicle.VehicleDamageEvent;
|
||||
import org.bukkit.event.vehicle.VehicleDestroyEvent;
|
||||
import org.bukkit.event.world.StructureGrowEvent;
|
||||
import org.bukkit.inventory.InventoryHolder;
|
||||
import org.bukkit.inventory.ItemStack;
|
||||
import org.bukkit.material.*;
|
||||
import org.bukkit.material.Dispenser;
|
||||
import org.bukkit.material.MaterialData;
|
||||
import org.bukkit.material.SpawnEgg;
|
||||
import org.bukkit.projectiles.ProjectileSource;
|
||||
import org.bukkit.util.Vector;
|
||||
|
||||
@@ -93,6 +93,16 @@ public class EventAbstractionListener extends AbstractListener {
|
||||
super(plugin);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void registerEvents() {
|
||||
super.registerEvents();
|
||||
|
||||
try {
|
||||
getPlugin().getServer().getPluginManager().registerEvents(new SpigotCompatListener(), getPlugin());
|
||||
} catch (LinkageError ignored) {
|
||||
}
|
||||
}
|
||||
|
||||
//-------------------------------------------------------------------------
|
||||
// Block break / place
|
||||
//-------------------------------------------------------------------------
|
||||
@@ -232,18 +242,28 @@ public class EventAbstractionListener extends AbstractListener {
|
||||
Events.fireBulkEventToCancel(event, new BreakBlockEvent(event, create(entity), event.getLocation().getWorld(), event.blockList(), Material.AIR));
|
||||
}
|
||||
|
||||
@SuppressWarnings("deprecation")
|
||||
@EventHandler(ignoreCancelled = true)
|
||||
public void onBlockPistonRetract(BlockPistonRetractEvent event) {
|
||||
if (event.isSticky()) {
|
||||
EventDebounce.Entry entry = pistonRetractDebounce.getIfNotPresent(new BlockPistonRetractKey(event), event);
|
||||
if (entry != null) {
|
||||
Cause cause = create(event.getBlock());
|
||||
Events.fireToCancel(event, new BreakBlockEvent(event, cause, event.getRetractLocation(), Material.AIR));
|
||||
Events.fireToCancel(event, new PlaceBlockEvent(event, cause, event.getBlock().getRelative(event.getDirection())));
|
||||
Block piston = event.getBlock();
|
||||
Cause cause = create(piston);
|
||||
|
||||
// Workaround for incorrect piston events
|
||||
BlockFace direction = event.getDirection();
|
||||
if (piston.getType() == Material.PISTON_MOVING_PIECE) {
|
||||
direction = new PistonExtensionMaterial(Material.PISTON_STICKY_BASE.getId(), piston.getData()).getFacing();
|
||||
}
|
||||
Location retractLocation = piston.getRelative(direction, 2).getLocation();
|
||||
|
||||
Events.fireToCancel(event, new BreakBlockEvent(event, cause, retractLocation, Material.AIR));
|
||||
Events.fireToCancel(event, new PlaceBlockEvent(event, cause, piston.getRelative(direction)));
|
||||
entry.setCancelled(event.isCancelled());
|
||||
|
||||
if (event.isCancelled()) {
|
||||
playDenyEffect(event.getBlock().getLocation().add(0.5, 1, 0.5));
|
||||
playDenyEffect(piston.getLocation().add(0.5, 1, 0.5));
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -292,6 +312,7 @@ public class EventAbstractionListener extends AbstractListener {
|
||||
Block clicked = event.getClickedBlock();
|
||||
Block placed;
|
||||
boolean silent = false;
|
||||
boolean modifiesWorld;
|
||||
Cause cause = create(player);
|
||||
|
||||
switch (event.getAction()) {
|
||||
@@ -301,9 +322,8 @@ public class EventAbstractionListener extends AbstractListener {
|
||||
silent = true;
|
||||
}
|
||||
|
||||
if (!hasInteractBypass(clicked)) {
|
||||
interactDebounce.debounce(clicked, event.getPlayer(), event, DelegateEvents.setSilent(new UseBlockEvent(event, cause, clicked), silent));
|
||||
}
|
||||
interactDebounce.debounce(clicked, event.getPlayer(), event,
|
||||
new UseBlockEvent(event, cause, clicked).setSilent(silent).setAllowed(hasInteractBypass(clicked)));
|
||||
break;
|
||||
|
||||
case RIGHT_CLICK_BLOCK:
|
||||
@@ -316,17 +336,17 @@ public class EventAbstractionListener extends AbstractListener {
|
||||
placed = clicked.getRelative(event.getBlockFace());
|
||||
|
||||
// Only fire events for blocks that are modified when right clicked
|
||||
if (isBlockModifiedOnClick(clicked) || (item != null && isItemAppliedToBlock(item, clicked))) {
|
||||
if (Events.fireAndTestCancel(new UseBlockEvent(event, cause, clicked))) {
|
||||
event.setUseInteractedBlock(Result.DENY);
|
||||
}
|
||||
modifiesWorld = isBlockModifiedOnClick(clicked, event.getAction() == Action.RIGHT_CLICK_BLOCK) || (item != null && isItemAppliedToBlock(item, clicked));
|
||||
|
||||
// Handle connected blocks (i.e. beds, chests)
|
||||
for (Block connected : Blocks.getConnected(clicked)) {
|
||||
if (Events.fireAndTestCancel(new UseBlockEvent(event, create(event.getPlayer()), connected))) {
|
||||
event.setUseInteractedBlock(Result.DENY);
|
||||
break;
|
||||
}
|
||||
if (Events.fireAndTestCancel(new UseBlockEvent(event, cause, clicked).setAllowed(!modifiesWorld))) {
|
||||
event.setUseInteractedBlock(Result.DENY);
|
||||
}
|
||||
|
||||
// Handle connected blocks (i.e. beds, chests)
|
||||
for (Block connected : Blocks.getConnected(clicked)) {
|
||||
if (Events.fireAndTestCancel(new UseBlockEvent(event, create(event.getPlayer()), connected).setAllowed(!modifiesWorld))) {
|
||||
event.setUseInteractedBlock(Result.DENY);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -365,9 +385,8 @@ public class EventAbstractionListener extends AbstractListener {
|
||||
|
||||
@EventHandler(ignoreCancelled = true)
|
||||
public void onEntityInteract(org.bukkit.event.entity.EntityInteractEvent event) {
|
||||
if (!hasInteractBypass(event.getBlock())) {
|
||||
interactDebounce.debounce(event.getBlock(), event.getEntity(), event, new UseBlockEvent(event, create(event.getEntity()), event.getBlock()));
|
||||
}
|
||||
interactDebounce.debounce(event.getBlock(), event.getEntity(), event,
|
||||
new UseBlockEvent(event, create(event.getEntity()), event.getBlock()).setAllowed(hasInteractBypass(event.getBlock())));
|
||||
}
|
||||
|
||||
@EventHandler(ignoreCancelled = true)
|
||||
@@ -408,31 +427,41 @@ public class EventAbstractionListener extends AbstractListener {
|
||||
public void onPlayerBucketEmpty(PlayerBucketEmptyEvent event) {
|
||||
Player player = event.getPlayer();
|
||||
Block blockAffected = event.getBlockClicked().getRelative(event.getBlockFace());
|
||||
boolean allowed = false;
|
||||
|
||||
// Milk buckets can't be emptied as of writing
|
||||
if (event.getBucket() != Material.MILK_BUCKET) {
|
||||
ItemStack item = new ItemStack(event.getBucket(), 1);
|
||||
Material blockMaterial = Materials.getBucketBlockMaterial(event.getBucket());
|
||||
Events.fireToCancel(event, new PlaceBlockEvent(event, create(player), blockAffected.getLocation(), blockMaterial));
|
||||
Events.fireToCancel(event, new UseItemEvent(event, create(player), player.getWorld(), item));
|
||||
if (event.getBucket() == Material.MILK_BUCKET) {
|
||||
allowed = true;
|
||||
}
|
||||
|
||||
playDenyEffect(event.getPlayer(), blockAffected.getLocation().add(0.5, 0.5, 0.5));
|
||||
ItemStack item = new ItemStack(event.getBucket(), 1);
|
||||
Material blockMaterial = Materials.getBucketBlockMaterial(event.getBucket());
|
||||
Events.fireToCancel(event, new PlaceBlockEvent(event, create(player), blockAffected.getLocation(), blockMaterial).setAllowed(allowed));
|
||||
Events.fireToCancel(event, new UseItemEvent(event, create(player), player.getWorld(), item).setAllowed(allowed));
|
||||
|
||||
if (event.isCancelled()) {
|
||||
playDenyEffect(event.getPlayer(), blockAffected.getLocation().add(0.5, 0.5, 0.5));
|
||||
}
|
||||
}
|
||||
|
||||
@EventHandler(ignoreCancelled = true)
|
||||
public void onPlayerBucketFill(PlayerBucketFillEvent event) {
|
||||
Player player = event.getPlayer();
|
||||
Block blockAffected = event.getBlockClicked().getRelative(event.getBlockFace());
|
||||
boolean allowed = false;
|
||||
|
||||
// Milk buckets can't be filled by right clicking the ground as of writing
|
||||
if (event.getBucket() != Material.MILK_BUCKET) {
|
||||
ItemStack item = new ItemStack(event.getBucket(), 1);
|
||||
Events.fireToCancel(event, new BreakBlockEvent(event, create(player), blockAffected));
|
||||
Events.fireToCancel(event, new UseItemEvent(event, create(player), player.getWorld(), item));
|
||||
// Milk buckets can't be emptied as of writing
|
||||
if (event.getBucket() == Material.MILK_BUCKET) {
|
||||
allowed = true;
|
||||
}
|
||||
|
||||
playDenyEffect(event.getPlayer(), blockAffected.getLocation().add(0.5, 1, 0.5));
|
||||
ItemStack item = new ItemStack(event.getBucket(), 1);
|
||||
Events.fireToCancel(event, new BreakBlockEvent(event, create(player), blockAffected).setAllowed(allowed));
|
||||
Events.fireToCancel(event, new UseItemEvent(event, create(player), player.getWorld(), item).setAllowed(allowed));
|
||||
|
||||
if (event.isCancelled()) {
|
||||
playDenyEffect(event.getPlayer(), blockAffected.getLocation().add(0.5, 0.5, 0.5));
|
||||
}
|
||||
}
|
||||
|
||||
// TODO: Handle EntityPortalEnterEvent
|
||||
@@ -536,8 +565,6 @@ public class EventAbstractionListener extends AbstractListener {
|
||||
if (event.isCancelled() && remover instanceof Player) {
|
||||
playDenyEffect((Player) remover, event.getEntity().getLocation());
|
||||
}
|
||||
} else {
|
||||
Events.fireToCancel(event, new DestroyEntityEvent(event, Cause.unknown(), event.getEntity()));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -605,7 +632,13 @@ public class EventAbstractionListener extends AbstractListener {
|
||||
@EventHandler(ignoreCancelled = true)
|
||||
public void onEntityDamage(EntityDamageEvent event) {
|
||||
if (event instanceof EntityDamageByBlockEvent) {
|
||||
Events.fireToCancel(event, new DamageEntityEvent(event, create(((EntityDamageByBlockEvent) event).getDamager()), event.getEntity()));
|
||||
@Nullable Block attacker = ((EntityDamageByBlockEvent) event).getDamager();
|
||||
|
||||
// The attacker should NOT be null, but sometimes it is
|
||||
// See WORLDGUARD-3350
|
||||
if (attacker != null) {
|
||||
Events.fireToCancel(event, new DamageEntityEvent(event, create(attacker), event.getEntity()));
|
||||
}
|
||||
|
||||
} else if (event instanceof EntityDamageByEntityEvent) {
|
||||
EntityDamageByEntityEvent entityEvent = (EntityDamageByEntityEvent) event;
|
||||
@@ -622,9 +655,6 @@ public class EventAbstractionListener extends AbstractListener {
|
||||
Events.fireToCancel(event, new UseItemEvent(event, create(damager), event.getEntity().getWorld(), item));
|
||||
}
|
||||
}
|
||||
|
||||
} else {
|
||||
Events.fireToCancel(event, new DamageEntityEvent(event, Cause.unknown(), event.getEntity()));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -635,9 +665,6 @@ public class EventAbstractionListener extends AbstractListener {
|
||||
|
||||
} else if (event instanceof EntityCombustByEntityEvent) {
|
||||
Events.fireToCancel(event, new DamageEntityEvent(event, create(((EntityCombustByEntityEvent) event).getCombuster()), event.getEntity()));
|
||||
|
||||
} else {
|
||||
Events.fireToCancel(event, new DamageEntityEvent(event, Cause.unknown(), event.getEntity()));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -675,7 +702,7 @@ public class EventAbstractionListener extends AbstractListener {
|
||||
@EventHandler(ignoreCancelled = true)
|
||||
public void onVehicleDamage(VehicleDamageEvent event) {
|
||||
Entity attacker = event.getAttacker();
|
||||
Events.fireToCancel(event, new DestroyEntityEvent(event, create(attacker), event.getVehicle()));
|
||||
Events.fireToCancel(event, new DamageEntityEvent(event, create(attacker), event.getVehicle()));
|
||||
}
|
||||
|
||||
@EventHandler(ignoreCancelled = true)
|
||||
@@ -692,6 +719,18 @@ public class EventAbstractionListener extends AbstractListener {
|
||||
Events.fireToCancel(event, new UseItemEvent(event, create(event.getPlayer()), event.getPlayer().getWorld(), event.getItem()));
|
||||
}
|
||||
|
||||
@EventHandler(ignoreCancelled = true)
|
||||
public void onInventoryOpen(InventoryOpenEvent event) {
|
||||
InventoryHolder holder = event.getInventory().getHolder();
|
||||
if (holder instanceof BlockState) {
|
||||
Events.fireToCancel(event, new UseBlockEvent(event, create(event.getPlayer()), ((BlockState) holder).getBlock()));
|
||||
} else if (holder instanceof Entity) {
|
||||
if (!(holder instanceof Player)) {
|
||||
Events.fireToCancel(event, new UseEntityEvent(event, create(event.getPlayer()), (Entity) holder));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@EventHandler(ignoreCancelled = true)
|
||||
public void onInventoryMoveItem(InventoryMoveItemEvent event) {
|
||||
final InventoryHolder causeHolder = event.getInitiator().getHolder();
|
||||
@@ -813,6 +852,11 @@ public class EventAbstractionListener extends AbstractListener {
|
||||
Events.fireToCancel(event, new SpawnEntityEvent(event, cause, placed.getLocation().add(0.5, 0, 0.5), EntityType.BOAT));
|
||||
}
|
||||
|
||||
// Handle created armor stands
|
||||
if (item != null && item.getType() == Materials.ARMOR_STAND) {
|
||||
Events.fireToCancel(event, new SpawnEntityEvent(event, cause, placed.getLocation().add(0.5, 0, 0.5), EntityType.ARMOR_STAND));
|
||||
}
|
||||
|
||||
// Handle created spawn eggs
|
||||
if (item != null && item.getType() == Material.MONSTER_EGG) {
|
||||
MaterialData data = item.getData();
|
||||
@@ -863,8 +907,8 @@ public class EventAbstractionListener extends AbstractListener {
|
||||
return getWorldConfig(world).allowAllInteract.test(item);
|
||||
}
|
||||
|
||||
private boolean isBlockModifiedOnClick(Block block) {
|
||||
return Materials.isBlockModifiedOnClick(block.getType()) && !hasInteractBypass(block);
|
||||
private boolean isBlockModifiedOnClick(Block block, boolean rightClick) {
|
||||
return Materials.isBlockModifiedOnClick(block.getType(), rightClick) && !hasInteractBypass(block);
|
||||
}
|
||||
|
||||
private boolean isItemAppliedToBlock(ItemStack item, Block clicked) {
|
||||
@@ -882,4 +926,17 @@ public class EventAbstractionListener extends AbstractListener {
|
||||
location.getWorld().playEffect(location, Effect.SMOKE, BlockFace.UP);
|
||||
}
|
||||
|
||||
public class SpigotCompatListener implements Listener {
|
||||
@EventHandler(ignoreCancelled = true)
|
||||
public void onPlayerInteractAtEntity(PlayerInteractAtEntityEvent event){
|
||||
onPlayerInteractEntity(event);
|
||||
}
|
||||
|
||||
@EventHandler(ignoreCancelled = true)
|
||||
public void onBlockExplode(BlockExplodeEvent event) {
|
||||
Events.fireBulkEventToCancel(event, new BreakBlockEvent(event, create(event.getBlock()),
|
||||
event.getBlock().getLocation().getWorld(), event.blockList(), Material.AIR));
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1,251 +0,0 @@
|
||||
/*
|
||||
* WorldGuard, a suite of tools for Minecraft
|
||||
* Copyright (C) sk89q <http://www.sk89q.com>
|
||||
* Copyright (C) WorldGuard team and contributors
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify it
|
||||
* under the terms of the GNU Lesser General Public License as published by the
|
||||
* Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License
|
||||
* for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
package com.sk89q.worldguard.bukkit.listener;
|
||||
|
||||
import com.sk89q.worldguard.bukkit.ConfigurationManager;
|
||||
import com.sk89q.worldguard.bukkit.WorldConfiguration;
|
||||
import com.sk89q.worldguard.bukkit.WorldGuardPlugin;
|
||||
import com.sk89q.worldguard.bukkit.internal.RegionQueryUtil;
|
||||
import com.sk89q.worldguard.protection.ApplicableRegionSet;
|
||||
import com.sk89q.worldguard.protection.flags.DefaultFlag;
|
||||
import org.bukkit.GameMode;
|
||||
import org.bukkit.World;
|
||||
import org.bukkit.entity.Player;
|
||||
|
||||
import java.util.Collection;
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
|
||||
/**
|
||||
* This processes per-player state information and is also meant to be used
|
||||
* as a scheduled task.
|
||||
*
|
||||
* @author sk89q
|
||||
*/
|
||||
public class FlagStateManager implements Runnable {
|
||||
|
||||
public static final int RUN_DELAY = 20;
|
||||
|
||||
private WorldGuardPlugin plugin;
|
||||
private Map<String, PlayerFlagState> states;
|
||||
|
||||
/**
|
||||
* Construct the object.
|
||||
*
|
||||
* @param plugin The plugin instance
|
||||
*/
|
||||
public FlagStateManager(WorldGuardPlugin plugin) {
|
||||
this.plugin = plugin;
|
||||
|
||||
states = new HashMap<String, PlayerFlagState>();
|
||||
}
|
||||
|
||||
/**
|
||||
* Run the task.
|
||||
*/
|
||||
@Override
|
||||
public void run() {
|
||||
Collection<? extends Player> players = plugin.getServer().getOnlinePlayers();
|
||||
ConfigurationManager config = plugin.getGlobalStateManager();
|
||||
|
||||
for (Player player : players) {
|
||||
WorldConfiguration worldConfig = config.get(player.getWorld());
|
||||
|
||||
if (!worldConfig.useRegions) {
|
||||
continue;
|
||||
}
|
||||
|
||||
PlayerFlagState state;
|
||||
|
||||
synchronized (this) {
|
||||
state = states.get(player.getName());
|
||||
|
||||
if (state == null) {
|
||||
state = new PlayerFlagState();
|
||||
states.put(player.getName(), state);
|
||||
}
|
||||
}
|
||||
|
||||
ApplicableRegionSet applicable = plugin.getRegionContainer().createQuery().getApplicableRegions(player.getLocation());
|
||||
|
||||
if (!RegionQueryUtil.isInvincible(plugin, player, applicable)
|
||||
&& !plugin.getGlobalStateManager().hasGodMode(player)
|
||||
&& !(player.getGameMode() == GameMode.CREATIVE)) {
|
||||
processHeal(applicable, player, state);
|
||||
processFeed(applicable, player, state);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Process healing for a player.
|
||||
*
|
||||
* @param applicable The set of applicable regions
|
||||
* @param player The player to process healing flags on
|
||||
* @param state The player's state
|
||||
*/
|
||||
private void processHeal(ApplicableRegionSet applicable, Player player,
|
||||
PlayerFlagState state) {
|
||||
|
||||
if (player.getHealth() <= 0) {
|
||||
return;
|
||||
}
|
||||
|
||||
long now = System.currentTimeMillis();
|
||||
|
||||
Integer healAmount = applicable.getFlag(DefaultFlag.HEAL_AMOUNT);
|
||||
Integer healDelay = applicable.getFlag(DefaultFlag.HEAL_DELAY);
|
||||
Double minHealth = applicable.getFlag(DefaultFlag.MIN_HEAL);
|
||||
Double maxHealth = applicable.getFlag(DefaultFlag.MAX_HEAL);
|
||||
|
||||
if (healAmount == null || healDelay == null || healAmount == 0 || healDelay < 0) {
|
||||
return;
|
||||
}
|
||||
if (minHealth == null) {
|
||||
minHealth = 0.0;
|
||||
}
|
||||
if (maxHealth == null) {
|
||||
maxHealth = player.getMaxHealth();
|
||||
}
|
||||
|
||||
// Apply a cap to prevent possible exceptions
|
||||
minHealth = Math.min(player.getMaxHealth(), minHealth);
|
||||
maxHealth = Math.min(player.getMaxHealth(), maxHealth);
|
||||
|
||||
if (player.getHealth() >= maxHealth && healAmount > 0) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (healDelay <= 0) {
|
||||
player.setHealth(healAmount > 0 ? maxHealth : minHealth); // this will insta-kill if the flag is unset
|
||||
state.lastHeal = now;
|
||||
} else if (now - state.lastHeal > healDelay * 1000) {
|
||||
// clamp health between minimum and maximum
|
||||
player.setHealth(Math.min(maxHealth, Math.max(minHealth, player.getHealth() + healAmount)));
|
||||
state.lastHeal = now;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Process restoring hunger for a player.
|
||||
*
|
||||
* @param applicable The set of applicable regions
|
||||
* @param player The player to process hunger flags on
|
||||
* @param state The player's state
|
||||
*/
|
||||
private void processFeed(ApplicableRegionSet applicable, Player player,
|
||||
PlayerFlagState state) {
|
||||
|
||||
long now = System.currentTimeMillis();
|
||||
|
||||
Integer feedAmount = applicable.getFlag(DefaultFlag.FEED_AMOUNT);
|
||||
Integer feedDelay = applicable.getFlag(DefaultFlag.FEED_DELAY);
|
||||
Integer minHunger = applicable.getFlag(DefaultFlag.MIN_FOOD);
|
||||
Integer maxHunger = applicable.getFlag(DefaultFlag.MAX_FOOD);
|
||||
|
||||
if (feedAmount == null || feedDelay == null || feedAmount == 0 || feedDelay < 0) {
|
||||
return;
|
||||
}
|
||||
if (minHunger == null) {
|
||||
minHunger = 0;
|
||||
}
|
||||
if (maxHunger == null) {
|
||||
maxHunger = 20;
|
||||
}
|
||||
|
||||
// Apply a cap to prevent possible exceptions
|
||||
minHunger = Math.min(20, minHunger);
|
||||
maxHunger = Math.min(20, maxHunger);
|
||||
|
||||
if (player.getFoodLevel() >= maxHunger && feedAmount > 0) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (feedDelay <= 0) {
|
||||
player.setFoodLevel(feedAmount > 0 ? maxHunger : minHunger);
|
||||
player.setSaturation(player.getFoodLevel());
|
||||
state.lastFeed = now;
|
||||
} else if (now - state.lastFeed > feedDelay * 1000) {
|
||||
// clamp health between minimum and maximum
|
||||
player.setFoodLevel(Math.min(maxHunger, Math.max(minHunger, player.getFoodLevel() + feedAmount)));
|
||||
player.setSaturation(player.getFoodLevel());
|
||||
state.lastFeed = now;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Forget a player.
|
||||
*
|
||||
* @param player The player to forget
|
||||
*/
|
||||
public synchronized void forget(Player player) {
|
||||
states.remove(player.getName());
|
||||
}
|
||||
|
||||
/**
|
||||
* Forget all managed players. Use with caution.
|
||||
*/
|
||||
public synchronized void forgetAll() {
|
||||
states.clear();
|
||||
}
|
||||
|
||||
/**
|
||||
* Get a player's flag state. A new state will be created if there is no existing
|
||||
* state for the player.
|
||||
*
|
||||
* @param player The player to get a state for
|
||||
* @return The {@code player}'s state
|
||||
*/
|
||||
public synchronized PlayerFlagState getState(Player player) {
|
||||
PlayerFlagState state = states.get(player.getName());
|
||||
|
||||
if (state == null) {
|
||||
state = new PlayerFlagState();
|
||||
states.put(player.getName(), state);
|
||||
}
|
||||
|
||||
return state;
|
||||
}
|
||||
|
||||
/**
|
||||
* Keeps state per player.
|
||||
*/
|
||||
public static class PlayerFlagState {
|
||||
public long lastHeal;
|
||||
public long lastFeed;
|
||||
public String lastGreeting;
|
||||
public String lastFarewell;
|
||||
public Boolean lastExitAllowed = null;
|
||||
public Boolean notifiedForLeave = false;
|
||||
public Boolean notifiedForEnter = false;
|
||||
public GameMode lastGameMode;
|
||||
public World lastWorld;
|
||||
public int lastBlockX;
|
||||
public int lastBlockY;
|
||||
public int lastBlockZ;
|
||||
|
||||
/* Used to cache invincibility status */
|
||||
public World lastInvincibleWorld;
|
||||
public int lastInvincibleX;
|
||||
public int lastInvincibleY;
|
||||
public int lastInvincibleZ;
|
||||
public boolean wasInvincible;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,105 @@
|
||||
/*
|
||||
* WorldGuard, a suite of tools for Minecraft
|
||||
* Copyright (C) sk89q <http://www.sk89q.com>
|
||||
* Copyright (C) WorldGuard team and contributors
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify it
|
||||
* under the terms of the GNU Lesser General Public License as published by the
|
||||
* Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License
|
||||
* for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
package com.sk89q.worldguard.bukkit.listener;
|
||||
|
||||
import com.sk89q.worldguard.bukkit.WorldConfiguration;
|
||||
import com.sk89q.worldguard.bukkit.WorldGuardPlugin;
|
||||
import org.bukkit.entity.Entity;
|
||||
import org.bukkit.entity.LivingEntity;
|
||||
import org.bukkit.entity.Player;
|
||||
import org.bukkit.entity.Tameable;
|
||||
import org.bukkit.event.EventHandler;
|
||||
import org.bukkit.event.entity.EntityCombustEvent;
|
||||
import org.bukkit.event.entity.EntityDamageByEntityEvent;
|
||||
import org.bukkit.event.entity.EntityDamageEvent;
|
||||
import org.bukkit.event.entity.FoodLevelChangeEvent;
|
||||
|
||||
public class InvincibilityListener extends AbstractListener {
|
||||
|
||||
/**
|
||||
* Construct the listener.
|
||||
*
|
||||
* @param plugin an instance of WorldGuardPlugin
|
||||
*/
|
||||
public InvincibilityListener(WorldGuardPlugin plugin) {
|
||||
super(plugin);
|
||||
}
|
||||
|
||||
/**
|
||||
* Test whether a player should be invincible.
|
||||
*
|
||||
* @param player The player
|
||||
* @return True if invincible
|
||||
*/
|
||||
private boolean isInvincible(Player player) {
|
||||
return getPlugin().getSessionManager().get(player).isInvincible(player);
|
||||
}
|
||||
|
||||
@EventHandler(ignoreCancelled = true)
|
||||
public void onEntityDamage(EntityDamageEvent event) {
|
||||
Entity victim = event.getEntity();
|
||||
WorldConfiguration worldConfig = getPlugin().getGlobalStateManager().get(victim.getWorld());
|
||||
|
||||
if (victim instanceof Player) {
|
||||
Player player = (Player) victim;
|
||||
|
||||
if (isInvincible(player)) {
|
||||
player.setFireTicks(0);
|
||||
event.setCancelled(true);
|
||||
|
||||
if (event instanceof EntityDamageByEntityEvent) {
|
||||
EntityDamageByEntityEvent byEntityEvent = (EntityDamageByEntityEvent) event;
|
||||
Entity attacker = byEntityEvent.getDamager();
|
||||
|
||||
if (worldConfig.regionInvinciblityRemovesMobs
|
||||
&& attacker instanceof LivingEntity && !(attacker instanceof Player)
|
||||
&& !(attacker instanceof Tameable && ((Tameable) attacker).isTamed())) {
|
||||
attacker.remove();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@EventHandler(ignoreCancelled = true)
|
||||
public void onEntityCombust(EntityCombustEvent event) {
|
||||
Entity entity = event.getEntity();
|
||||
|
||||
if (entity instanceof Player) {
|
||||
Player player = (Player) entity;
|
||||
|
||||
if (isInvincible(player)) {
|
||||
event.setCancelled(true);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@EventHandler(ignoreCancelled = true)
|
||||
public void onFoodLevelChange(FoodLevelChangeEvent event) {
|
||||
if (event.getEntity() instanceof Player) {
|
||||
Player player = (Player) event.getEntity();
|
||||
|
||||
if (event.getFoodLevel() < player.getFoodLevel() && isInvincible(player)) {
|
||||
event.setCancelled(true);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
@@ -22,6 +22,9 @@ package com.sk89q.worldguard.bukkit.listener;
|
||||
import com.sk89q.worldguard.bukkit.ConfigurationManager;
|
||||
import com.sk89q.worldguard.bukkit.WorldGuardPlugin;
|
||||
import com.sk89q.worldguard.bukkit.event.player.ProcessPlayerEvent;
|
||||
import com.sk89q.worldguard.session.Session;
|
||||
import com.sk89q.worldguard.session.handler.GodMode;
|
||||
import com.sk89q.worldguard.session.handler.WaterBreathing;
|
||||
import org.bukkit.entity.Player;
|
||||
import org.bukkit.event.EventHandler;
|
||||
|
||||
@@ -61,17 +64,18 @@ public class PlayerModesListener extends AbstractListener {
|
||||
public void onProcessPlayer(ProcessPlayerEvent event) {
|
||||
ConfigurationManager config = getConfig();
|
||||
Player player = event.getPlayer();
|
||||
Session session = getPlugin().getSessionManager().get(player);
|
||||
|
||||
if (!config.hasCommandBookGodMode()) {
|
||||
if (hasGodModeGroup(player) || hasGodModePermission(player)) {
|
||||
if (hasGodModeGroup(player) || hasGodModePermission(player)) {
|
||||
if (GodMode.set(player, session, true)) {
|
||||
log.log(Level.INFO, "Enabled auto-god mode for " + player.getName());
|
||||
config.enableGodMode(player);
|
||||
}
|
||||
}
|
||||
|
||||
if (hasAmphibiousGroup(player)) {
|
||||
log.log(Level.INFO, "Enabled no-drowning mode for " + player.getName() + " (player is in group 'wg-amphibious')");
|
||||
config.enableAmphibiousMode(player);
|
||||
if (WaterBreathing.set(player, session, true)) {
|
||||
log.log(Level.INFO, "Enabled water breathing mode for " + player.getName() + " (player is in group 'wg-amphibious')");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -19,46 +19,26 @@
|
||||
|
||||
package com.sk89q.worldguard.bukkit.listener;
|
||||
|
||||
import com.sk89q.worldedit.Vector;
|
||||
import com.sk89q.worldguard.LocalPlayer;
|
||||
import com.sk89q.worldguard.bukkit.BukkitUtil;
|
||||
import com.sk89q.worldguard.bukkit.ConfigurationManager;
|
||||
import com.sk89q.worldguard.bukkit.WorldConfiguration;
|
||||
import com.sk89q.worldguard.bukkit.WorldGuardPlugin;
|
||||
import com.sk89q.worldguard.bukkit.listener.FlagStateManager.PlayerFlagState;
|
||||
import com.sk89q.guavabackport.cache.CacheBuilder;
|
||||
import com.sk89q.guavabackport.cache.CacheLoader;
|
||||
import com.sk89q.guavabackport.cache.LoadingCache;
|
||||
import com.sk89q.worldguard.protection.ApplicableRegionSet;
|
||||
import com.sk89q.worldguard.protection.flags.DefaultFlag;
|
||||
import com.sk89q.worldguard.protection.managers.RegionManager;
|
||||
import com.sk89q.worldguard.protection.regions.ProtectedRegion;
|
||||
import org.bukkit.ChatColor;
|
||||
import org.bukkit.GameMode;
|
||||
import com.sk89q.worldguard.session.MoveType;
|
||||
import com.sk89q.worldguard.session.Session;
|
||||
import org.bukkit.Bukkit;
|
||||
import org.bukkit.Location;
|
||||
import org.bukkit.World;
|
||||
import org.bukkit.entity.Entity;
|
||||
import org.bukkit.entity.LivingEntity;
|
||||
import org.bukkit.entity.Player;
|
||||
import org.bukkit.event.EventHandler;
|
||||
import org.bukkit.event.EventPriority;
|
||||
import org.bukkit.event.Listener;
|
||||
import org.bukkit.event.player.PlayerMoveEvent;
|
||||
import org.bukkit.event.player.PlayerRespawnEvent;
|
||||
import org.bukkit.event.vehicle.VehicleEnterEvent;
|
||||
import org.bukkit.plugin.PluginManager;
|
||||
|
||||
import java.util.concurrent.TimeUnit;
|
||||
import org.bukkit.util.Vector;
|
||||
|
||||
public class PlayerMoveListener implements Listener {
|
||||
|
||||
private final WorldGuardPlugin plugin;
|
||||
private LoadingCache<WorldPlayerTuple, Boolean> bypassCache = CacheBuilder.newBuilder()
|
||||
.maximumSize(1000)
|
||||
.expireAfterAccess(5, TimeUnit.SECONDS)
|
||||
.build(new CacheLoader<WorldPlayerTuple, Boolean>() {
|
||||
@Override
|
||||
public Boolean load(WorldPlayerTuple tuple) throws Exception {
|
||||
return plugin.getGlobalRegionManager().hasBypass(tuple.player, tuple.world);
|
||||
}
|
||||
});
|
||||
|
||||
public PlayerMoveListener(WorldGuardPlugin plugin) {
|
||||
this.plugin = plugin;
|
||||
@@ -71,196 +51,68 @@ public class PlayerMoveListener implements Listener {
|
||||
}
|
||||
}
|
||||
|
||||
private boolean hasBypass(Player player, World world) {
|
||||
return bypassCache.getUnchecked(new WorldPlayerTuple(world, player));
|
||||
@EventHandler
|
||||
public void onPlayerRespawn(PlayerRespawnEvent event) {
|
||||
Player player = event.getPlayer();
|
||||
|
||||
Session session = plugin.getSessionManager().get(player);
|
||||
session.testMoveTo(player, event.getRespawnLocation(), MoveType.RESPAWN, true);
|
||||
}
|
||||
|
||||
/**
|
||||
* Handles movement related events, including changing gamemode, sending
|
||||
* greeting/farewell messages, etc.
|
||||
*
|
||||
* @param from The before location
|
||||
* @param to The to location
|
||||
* @return True if the movement should not be allowed
|
||||
*/
|
||||
public boolean shouldDenyMove(Player player, Location from, Location to) {
|
||||
PlayerFlagState state = plugin.getFlagStateManager().getState(player);
|
||||
|
||||
// Flush states in multi-world scenario
|
||||
if (state.lastWorld != null && !state.lastWorld.equals(to.getWorld())) {
|
||||
plugin.getFlagStateManager().forget(player);
|
||||
state = plugin.getFlagStateManager().getState(player);
|
||||
}
|
||||
|
||||
// TODO: Clean up this disaster
|
||||
|
||||
World world = from.getWorld();
|
||||
World toWorld = to.getWorld();
|
||||
|
||||
LocalPlayer localPlayer = plugin.wrapPlayer(player);
|
||||
boolean hasBypass = hasBypass(player, world);
|
||||
boolean hasRemoteBypass;
|
||||
if (world.equals(toWorld)) {
|
||||
hasRemoteBypass = hasBypass;
|
||||
} else {
|
||||
hasRemoteBypass = hasBypass(player, toWorld);
|
||||
}
|
||||
|
||||
RegionManager regions = plugin.getGlobalRegionManager().get(toWorld);
|
||||
if (regions == null) {
|
||||
return false;
|
||||
}
|
||||
|
||||
Vector pt = new Vector(to.getBlockX(), to.getBlockY(), to.getBlockZ());
|
||||
ApplicableRegionSet set = regions.getApplicableRegions(pt);
|
||||
|
||||
boolean entryAllowed = set.allows(DefaultFlag.ENTRY, localPlayer);
|
||||
if (!hasRemoteBypass && !entryAllowed) {
|
||||
player.sendMessage(ChatColor.DARK_RED + "You are not permitted to enter this area.");
|
||||
return true;
|
||||
}
|
||||
|
||||
// Have to set this state
|
||||
if (state.lastExitAllowed == null) {
|
||||
state.lastExitAllowed = plugin.getRegionContainer().createQuery().getApplicableRegions(from).allows(DefaultFlag.EXIT, localPlayer);
|
||||
}
|
||||
|
||||
boolean exitAllowed = set.allows(DefaultFlag.EXIT, localPlayer);
|
||||
if (!hasBypass && exitAllowed && !state.lastExitAllowed) {
|
||||
player.sendMessage(ChatColor.DARK_RED + "You are not permitted to leave this area.");
|
||||
return true;
|
||||
}
|
||||
|
||||
String greeting = set.getFlag(DefaultFlag.GREET_MESSAGE);
|
||||
String farewell = set.getFlag(DefaultFlag.FAREWELL_MESSAGE);
|
||||
Boolean notifyEnter = set.getFlag(DefaultFlag.NOTIFY_ENTER);
|
||||
Boolean notifyLeave = set.getFlag(DefaultFlag.NOTIFY_LEAVE);
|
||||
GameMode gameMode = set.getFlag(DefaultFlag.GAME_MODE);
|
||||
|
||||
if (state.lastFarewell != null && (farewell == null || !state.lastFarewell.equals(farewell))) {
|
||||
String replacedFarewell = plugin.replaceMacros(player, BukkitUtil.replaceColorMacros(state.lastFarewell));
|
||||
player.sendMessage(replacedFarewell.replaceAll("\\\\n", "\n").split("\\n"));
|
||||
}
|
||||
|
||||
if (greeting != null && (state.lastGreeting == null || !state.lastGreeting.equals(greeting))) {
|
||||
String replacedGreeting = plugin.replaceMacros(player, BukkitUtil.replaceColorMacros(greeting));
|
||||
player.sendMessage(replacedGreeting.replaceAll("\\\\n", "\n").split("\\n"));
|
||||
}
|
||||
|
||||
if ((notifyLeave == null || !notifyLeave) && state.notifiedForLeave != null && state.notifiedForLeave) {
|
||||
plugin.broadcastNotification(ChatColor.GRAY + "WG: "
|
||||
+ ChatColor.LIGHT_PURPLE + player.getName()
|
||||
+ ChatColor.GOLD + " left NOTIFY region");
|
||||
}
|
||||
|
||||
if (notifyEnter != null && notifyEnter && (state.notifiedForEnter == null || !state.notifiedForEnter)) {
|
||||
StringBuilder regionList = new StringBuilder();
|
||||
|
||||
for (ProtectedRegion region : set) {
|
||||
if (regionList.length() != 0) {
|
||||
regionList.append(", ");
|
||||
}
|
||||
|
||||
regionList.append(region.getId());
|
||||
}
|
||||
|
||||
plugin.broadcastNotification(ChatColor.GRAY + "WG: "
|
||||
+ ChatColor.LIGHT_PURPLE + player.getName()
|
||||
+ ChatColor.GOLD + " entered NOTIFY region: "
|
||||
+ ChatColor.WHITE
|
||||
+ regionList);
|
||||
}
|
||||
|
||||
if (!hasBypass && gameMode != null) {
|
||||
if (player.getGameMode() != gameMode) {
|
||||
state.lastGameMode = player.getGameMode();
|
||||
player.setGameMode(gameMode);
|
||||
} else if (state.lastGameMode == null) {
|
||||
state.lastGameMode = player.getServer().getDefaultGameMode();
|
||||
}
|
||||
} else {
|
||||
if (state.lastGameMode != null) {
|
||||
GameMode mode = state.lastGameMode;
|
||||
state.lastGameMode = null;
|
||||
player.setGameMode(mode);
|
||||
@EventHandler
|
||||
public void onVehicleEnter(VehicleEnterEvent event) {
|
||||
Entity entity = event.getEntered();
|
||||
if (entity instanceof Player) {
|
||||
Player player = (Player) entity;
|
||||
Session session = plugin.getSessionManager().get(player);
|
||||
if (null != session.testMoveTo(player, event.getVehicle().getLocation(), MoveType.EMBARK, true)) {
|
||||
event.setCancelled(true);
|
||||
}
|
||||
}
|
||||
|
||||
state.lastGreeting = greeting;
|
||||
state.lastFarewell = farewell;
|
||||
state.notifiedForEnter = notifyEnter;
|
||||
state.notifiedForLeave = notifyLeave;
|
||||
state.lastExitAllowed = exitAllowed;
|
||||
state.lastWorld = to.getWorld();
|
||||
state.lastBlockX = to.getBlockX();
|
||||
state.lastBlockY = to.getBlockY();
|
||||
state.lastBlockZ = to.getBlockZ();
|
||||
return false;
|
||||
}
|
||||
|
||||
@EventHandler(priority = EventPriority.HIGH)
|
||||
public void onPlayerMove(PlayerMoveEvent event) {
|
||||
final Player player = event.getPlayer();
|
||||
World world = player.getWorld();
|
||||
|
||||
ConfigurationManager cfg = plugin.getGlobalStateManager();
|
||||
WorldConfiguration wcfg = cfg.get(world);
|
||||
Session session = plugin.getSessionManager().get(player);
|
||||
final Location override = session.testMoveTo(player, event.getTo(), MoveType.MOVE);
|
||||
|
||||
if (wcfg.useRegions) {
|
||||
if (hasMoved(event.getFrom(), event.getTo())) {
|
||||
if (shouldDenyMove(player, event.getFrom(), event.getTo())) {
|
||||
Location newLoc = event.getFrom();
|
||||
newLoc.setX(newLoc.getBlockX() + 0.5);
|
||||
newLoc.setY(newLoc.getBlockY());
|
||||
newLoc.setZ(newLoc.getBlockZ() + 0.5);
|
||||
event.setTo(newLoc);
|
||||
if (override != null) {
|
||||
override.setX(override.getBlockX() + 0.5);
|
||||
override.setY(override.getBlockY());
|
||||
override.setZ(override.getBlockZ() + 0.5);
|
||||
override.setPitch(event.getTo().getPitch());
|
||||
override.setYaw(event.getTo().getYaw());
|
||||
|
||||
Entity vehicle = player.getVehicle();
|
||||
if (vehicle != null) {
|
||||
vehicle.eject();
|
||||
vehicle.teleport(newLoc);
|
||||
player.teleport(newLoc);
|
||||
vehicle.setPassenger(player);
|
||||
event.setTo(override.clone());
|
||||
|
||||
Entity vehicle = player.getVehicle();
|
||||
if (vehicle != null) {
|
||||
vehicle.eject();
|
||||
|
||||
Entity current = vehicle;
|
||||
while (current != null) {
|
||||
current.eject();
|
||||
vehicle.setVelocity(new Vector());
|
||||
if (vehicle instanceof LivingEntity) {
|
||||
vehicle.teleport(override.clone());
|
||||
} else {
|
||||
vehicle.teleport(override.clone().add(0, 1, 0));
|
||||
}
|
||||
current = current.getVehicle();
|
||||
}
|
||||
|
||||
player.teleport(override.clone().add(0, 1, 0));
|
||||
|
||||
Bukkit.getScheduler().runTaskLater(plugin, new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
player.teleport(override.clone().add(0, 1, 0));
|
||||
}
|
||||
}, 1);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private static boolean hasMoved(Location loc1, Location loc2) {
|
||||
return loc1.getBlockX() != loc2.getBlockX()
|
||||
|| loc1.getBlockY() != loc2.getBlockY()
|
||||
|| loc1.getBlockZ() != loc2.getBlockZ();
|
||||
}
|
||||
|
||||
private static class WorldPlayerTuple {
|
||||
private final World world;
|
||||
private final Player player;
|
||||
|
||||
private WorldPlayerTuple(World world, Player player) {
|
||||
this.world = world;
|
||||
this.player = player;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean equals(Object o) {
|
||||
if (this == o) return true;
|
||||
if (o == null || getClass() != o.getClass()) return false;
|
||||
|
||||
WorldPlayerTuple that = (WorldPlayerTuple) o;
|
||||
|
||||
if (!player.equals(that.player)) return false;
|
||||
if (!world.equals(that.world)) return false;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int hashCode() {
|
||||
int result = world.hashCode();
|
||||
result = 31 * result + player.hashCode();
|
||||
return result;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
@@ -30,12 +30,16 @@ import com.sk89q.worldguard.protection.association.RegionAssociable;
|
||||
import com.sk89q.worldguard.protection.flags.DefaultFlag;
|
||||
import com.sk89q.worldguard.protection.flags.StateFlag;
|
||||
import org.bukkit.Location;
|
||||
import org.bukkit.World;
|
||||
import org.bukkit.block.Block;
|
||||
import org.bukkit.entity.Creeper;
|
||||
import org.bukkit.entity.EnderDragon;
|
||||
import org.bukkit.entity.Entity;
|
||||
import org.bukkit.entity.Player;
|
||||
import org.bukkit.event.EventHandler;
|
||||
import org.bukkit.event.EventPriority;
|
||||
import org.bukkit.event.entity.EntityDamageEvent;
|
||||
import org.bukkit.event.entity.EntityDamageEvent.DamageCause;
|
||||
|
||||
import javax.annotation.Nullable;
|
||||
|
||||
@@ -87,7 +91,7 @@ public class RegionFlagsListener extends AbstractListener {
|
||||
}
|
||||
|
||||
Entity entity;
|
||||
if ((entity = event.getCause().getFirstEntity()) != null) {
|
||||
if ((entity = event.getCause().getFirstNonPlayerEntity()) != null) {
|
||||
// ================================================================
|
||||
// CREEPER_EXPLOSION flag
|
||||
// ================================================================
|
||||
@@ -107,6 +111,21 @@ public class RegionFlagsListener extends AbstractListener {
|
||||
}
|
||||
}
|
||||
|
||||
@EventHandler(priority = EventPriority.LOW, ignoreCancelled = true)
|
||||
public void onEntityDamage(EntityDamageEvent event) {
|
||||
Entity entity = event.getEntity();
|
||||
World world = entity.getWorld();
|
||||
|
||||
if (!isRegionSupportEnabled(world)) return; // Region support disabled
|
||||
RegionQuery query = getPlugin().getRegionContainer().createQuery();
|
||||
|
||||
if (entity instanceof Player && event.getCause() == DamageCause.FALL) {
|
||||
if (!query.testState(entity.getLocation(), (Player) entity, DefaultFlag.FALL_DAMAGE)) {
|
||||
event.setCancelled(true);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a new predicate to test a state flag for each location.
|
||||
*
|
||||
|
||||
@@ -38,6 +38,7 @@ import com.sk89q.worldguard.bukkit.protection.DelayedRegionOverlapAssociation;
|
||||
import com.sk89q.worldguard.bukkit.util.Entities;
|
||||
import com.sk89q.worldguard.bukkit.util.Events;
|
||||
import com.sk89q.worldguard.bukkit.util.Materials;
|
||||
import com.sk89q.worldguard.bukkit.util.InteropUtils;
|
||||
import com.sk89q.worldguard.domains.Association;
|
||||
import com.sk89q.worldguard.protection.association.Associables;
|
||||
import com.sk89q.worldguard.protection.association.RegionAssociable;
|
||||
@@ -48,6 +49,7 @@ import com.sk89q.worldguard.protection.flags.StateFlag.State;
|
||||
import org.bukkit.*;
|
||||
import org.bukkit.block.Block;
|
||||
import org.bukkit.entity.*;
|
||||
import org.bukkit.event.Event.Result;
|
||||
import org.bukkit.event.EventHandler;
|
||||
import org.bukkit.event.vehicle.VehicleExitEvent;
|
||||
|
||||
@@ -81,7 +83,7 @@ public class RegionProtectionListener extends AbstractListener {
|
||||
* @param what what was done
|
||||
*/
|
||||
private void tellErrorMessage(DelegateEvent event, Cause cause, Location location, String what) {
|
||||
if (event.isSilent()) {
|
||||
if (event.isSilent() || cause.isIndirect()) {
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -121,7 +123,7 @@ public class RegionProtectionListener extends AbstractListener {
|
||||
Player player = (Player) rootCause;
|
||||
WorldConfiguration config = getWorldConfig(world);
|
||||
|
||||
if (config.fakePlayerBuildOverride && Entities.isFakePlayer(player)) {
|
||||
if (config.fakePlayerBuildOverride && InteropUtils.isFakePlayer(player)) {
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -153,6 +155,7 @@ public class RegionProtectionListener extends AbstractListener {
|
||||
|
||||
@EventHandler(ignoreCancelled = true)
|
||||
public void onPlaceBlock(final PlaceBlockEvent event) {
|
||||
if (event.getResult() == Result.ALLOW) return; // Don't care about events that have been pre-allowed
|
||||
if (!isRegionSupportEnabled(event.getWorld())) return; // Region support disabled
|
||||
if (isWhitelisted(event.getCause(), event.getWorld(), false)) return; // Whitelisted cause
|
||||
|
||||
@@ -196,6 +199,7 @@ public class RegionProtectionListener extends AbstractListener {
|
||||
|
||||
@EventHandler(ignoreCancelled = true)
|
||||
public void onBreakBlock(final BreakBlockEvent event) {
|
||||
if (event.getResult() == Result.ALLOW) return; // Don't care about events that have been pre-allowed
|
||||
if (!isRegionSupportEnabled(event.getWorld())) return; // Region support disabled
|
||||
if (isWhitelisted(event.getCause(), event.getWorld(), false)) return; // Whitelisted cause
|
||||
|
||||
@@ -211,9 +215,9 @@ public class RegionProtectionListener extends AbstractListener {
|
||||
String what;
|
||||
|
||||
/* TNT */
|
||||
if (event.getCause().find(EntityType.PRIMED_TNT, EntityType.PRIMED_TNT) != null) {
|
||||
if (event.getCause().find(EntityType.PRIMED_TNT, EntityType.MINECART_TNT) != null) {
|
||||
canBreak = query.testBuild(target, associable, combine(event, DefaultFlag.BLOCK_BREAK, DefaultFlag.TNT));
|
||||
what = "dynamite blocks";
|
||||
what = "use dynamite";
|
||||
|
||||
/* Everything else */
|
||||
} else {
|
||||
@@ -234,6 +238,7 @@ public class RegionProtectionListener extends AbstractListener {
|
||||
|
||||
@EventHandler(ignoreCancelled = true)
|
||||
public void onUseBlock(final UseBlockEvent event) {
|
||||
if (event.getResult() == Result.ALLOW) return; // Don't care about events that have been pre-allowed
|
||||
if (!isRegionSupportEnabled(event.getWorld())) return; // Region support disabled
|
||||
if (isWhitelisted(event.getCause(), event.getWorld(), false)) return; // Whitelisted cause
|
||||
|
||||
@@ -290,6 +295,7 @@ public class RegionProtectionListener extends AbstractListener {
|
||||
|
||||
@EventHandler(ignoreCancelled = true)
|
||||
public void onSpawnEntity(SpawnEntityEvent event) {
|
||||
if (event.getResult() == Result.ALLOW) return; // Don't care about events that have been pre-allowed
|
||||
if (!isRegionSupportEnabled(event.getWorld())) return; // Region support disabled
|
||||
if (isWhitelisted(event.getCause(), event.getWorld(), false)) return; // Whitelisted cause
|
||||
|
||||
@@ -336,6 +342,7 @@ public class RegionProtectionListener extends AbstractListener {
|
||||
|
||||
@EventHandler(ignoreCancelled = true)
|
||||
public void onDestroyEntity(DestroyEntityEvent event) {
|
||||
if (event.getResult() == Result.ALLOW) return; // Don't care about events that have been pre-allowed
|
||||
if (!isRegionSupportEnabled(event.getWorld())) return; // Region support disabled
|
||||
if (isWhitelisted(event.getCause(), event.getWorld(), false)) return; // Whitelisted cause
|
||||
|
||||
@@ -371,6 +378,7 @@ public class RegionProtectionListener extends AbstractListener {
|
||||
|
||||
@EventHandler(ignoreCancelled = true)
|
||||
public void onUseEntity(UseEntityEvent event) {
|
||||
if (event.getResult() == Result.ALLOW) return; // Don't care about events that have been pre-allowed
|
||||
if (!isRegionSupportEnabled(event.getWorld())) return; // Region support disabled
|
||||
if (isWhitelisted(event.getCause(), event.getWorld(), false)) return; // Whitelisted cause
|
||||
|
||||
@@ -382,8 +390,9 @@ public class RegionProtectionListener extends AbstractListener {
|
||||
String what;
|
||||
|
||||
/* Hostile / ambient mob override */
|
||||
if (Entities.isHostile(event.getEntity()) || Entities.isAmbient(event.getEntity()) || Entities.isNPC(event.getEntity())) {
|
||||
canUse = event.getRelevantFlags().isEmpty() || query.testState(target, associable, combine(event));
|
||||
if (Entities.isHostile(event.getEntity()) || Entities.isAmbient(event.getEntity())
|
||||
|| Entities.isNPC(event.getEntity()) || Entities.isVehicle(event.getEntity().getType())) {
|
||||
canUse = event.getRelevantFlags().isEmpty() || query.queryState(target, associable, combine(event)) != State.DENY;
|
||||
what = "use that";
|
||||
|
||||
/* Paintings, item frames, etc. */
|
||||
@@ -410,6 +419,7 @@ public class RegionProtectionListener extends AbstractListener {
|
||||
|
||||
@EventHandler(ignoreCancelled = true)
|
||||
public void onDamageEntity(DamageEntityEvent event) {
|
||||
if (event.getResult() == Result.ALLOW) return; // Don't care about events that have been pre-allowed
|
||||
if (!isRegionSupportEnabled(event.getWorld())) return; // Region support disabled
|
||||
// Whitelist check is below
|
||||
|
||||
@@ -430,8 +440,9 @@ public class RegionProtectionListener extends AbstractListener {
|
||||
}
|
||||
|
||||
/* Hostile / ambient mob override */
|
||||
if (Entities.isHostile(event.getEntity()) || Entities.isAmbient(event.getEntity())) {
|
||||
canDamage = event.getRelevantFlags().isEmpty() || query.testState(target, associable, combine(event));
|
||||
if (Entities.isHostile(event.getEntity()) || Entities.isAmbient(event.getEntity())
|
||||
|| Entities.isVehicle(event.getEntity().getType())) {
|
||||
canDamage = event.getRelevantFlags().isEmpty() || query.queryState(target, associable, combine(event)) != State.DENY;
|
||||
what = "hit that";
|
||||
|
||||
/* Paintings, item frames, etc. */
|
||||
@@ -444,7 +455,8 @@ public class RegionProtectionListener extends AbstractListener {
|
||||
Player defender = (Player) event.getEntity();
|
||||
|
||||
canDamage = query.testBuild(target, associable, combine(event, DefaultFlag.PVP))
|
||||
&& query.queryState(playerAttacker.getLocation(), playerAttacker, combine(event, DefaultFlag.PVP)) != State.DENY;
|
||||
&& query.queryState(playerAttacker.getLocation(), playerAttacker, combine(event, DefaultFlag.PVP)) != State.DENY
|
||||
&& query.queryState(target, playerAttacker, combine(event, DefaultFlag.PVP)) != State.DENY;
|
||||
|
||||
// Fire the disallow PVP event
|
||||
if (!canDamage && Events.fireAndTestCancel(new DisallowedPVPEvent(playerAttacker, defender, event.getOriginalEvent()))) {
|
||||
@@ -455,9 +467,14 @@ public class RegionProtectionListener extends AbstractListener {
|
||||
|
||||
/* Player damage not caused by another player */
|
||||
} else if (event.getEntity() instanceof Player) {
|
||||
canDamage = event.getRelevantFlags().isEmpty() || query.testState(target, associable, combine(event));
|
||||
canDamage = event.getRelevantFlags().isEmpty() || query.queryState(target, associable, combine(event)) != State.DENY;
|
||||
what = "damage that";
|
||||
|
||||
/* damage to non-hostile mobs (e.g. animals) */
|
||||
} else if (Entities.isNonHostile(event.getEntity())) {
|
||||
canDamage = query.testBuild(target, associable, combine(event, DefaultFlag.DAMAGE_ANIMALS));
|
||||
what = "harm that";
|
||||
|
||||
/* Everything else */
|
||||
} else {
|
||||
canDamage = query.testBuild(target, associable, combine(event, DefaultFlag.INTERACT));
|
||||
|
||||
@@ -380,7 +380,7 @@ public class WorldGuardBlockListener implements Listener {
|
||||
return;
|
||||
}
|
||||
|
||||
int id = event.getChangedTypeId();
|
||||
int id = event.getBlock().getTypeId();
|
||||
|
||||
if (id == 13 && wcfg.noPhysicsGravel) {
|
||||
event.setCancelled(true);
|
||||
|
||||
@@ -21,59 +21,22 @@ package com.sk89q.worldguard.bukkit.listener;
|
||||
|
||||
import com.sk89q.worldedit.blocks.BlockID;
|
||||
import com.sk89q.worldguard.LocalPlayer;
|
||||
import com.sk89q.worldguard.bukkit.BukkitUtil;
|
||||
import com.sk89q.worldguard.bukkit.ConfigurationManager;
|
||||
import com.sk89q.worldguard.bukkit.RegionQuery;
|
||||
import com.sk89q.worldguard.bukkit.WorldConfiguration;
|
||||
import com.sk89q.worldguard.bukkit.WorldGuardPlugin;
|
||||
import com.sk89q.worldguard.bukkit.internal.RegionQueryUtil;
|
||||
import com.sk89q.worldguard.bukkit.*;
|
||||
import com.sk89q.worldguard.bukkit.util.Entities;
|
||||
import com.sk89q.worldguard.protection.ApplicableRegionSet;
|
||||
import com.sk89q.worldguard.protection.GlobalRegionManager;
|
||||
import com.sk89q.worldguard.protection.flags.DefaultFlag;
|
||||
import com.sk89q.worldguard.protection.managers.RegionManager;
|
||||
import org.bukkit.Location;
|
||||
import org.bukkit.World;
|
||||
import org.bukkit.block.Block;
|
||||
import org.bukkit.entity.Creeper;
|
||||
import org.bukkit.entity.EnderDragon;
|
||||
import org.bukkit.entity.Enderman;
|
||||
import org.bukkit.entity.Entity;
|
||||
import org.bukkit.entity.EntityType;
|
||||
import org.bukkit.entity.Fireball;
|
||||
import org.bukkit.entity.ItemFrame;
|
||||
import org.bukkit.entity.LivingEntity;
|
||||
import org.bukkit.entity.Player;
|
||||
import org.bukkit.entity.Projectile;
|
||||
import org.bukkit.entity.TNTPrimed;
|
||||
import org.bukkit.entity.Tameable;
|
||||
import org.bukkit.entity.ThrownPotion;
|
||||
import org.bukkit.entity.Wither;
|
||||
import org.bukkit.entity.WitherSkull;
|
||||
import org.bukkit.entity.Wolf;
|
||||
import org.bukkit.entity.*;
|
||||
import org.bukkit.entity.minecart.ExplosiveMinecart;
|
||||
import org.bukkit.event.EventHandler;
|
||||
import org.bukkit.event.EventPriority;
|
||||
import org.bukkit.event.Listener;
|
||||
import org.bukkit.event.entity.CreatureSpawnEvent;
|
||||
import org.bukkit.event.entity.*;
|
||||
import org.bukkit.event.entity.CreatureSpawnEvent.SpawnReason;
|
||||
import org.bukkit.event.entity.CreeperPowerEvent;
|
||||
import org.bukkit.event.entity.EntityBreakDoorEvent;
|
||||
import org.bukkit.event.entity.EntityChangeBlockEvent;
|
||||
import org.bukkit.event.entity.EntityCombustEvent;
|
||||
import org.bukkit.event.entity.EntityCreatePortalEvent;
|
||||
import org.bukkit.event.entity.EntityDamageByBlockEvent;
|
||||
import org.bukkit.event.entity.EntityDamageByEntityEvent;
|
||||
import org.bukkit.event.entity.EntityDamageEvent;
|
||||
import org.bukkit.event.entity.EntityDamageEvent.DamageCause;
|
||||
import org.bukkit.event.entity.EntityDeathEvent;
|
||||
import org.bukkit.event.entity.EntityExplodeEvent;
|
||||
import org.bukkit.event.entity.EntityInteractEvent;
|
||||
import org.bukkit.event.entity.EntityRegainHealthEvent;
|
||||
import org.bukkit.event.entity.ExplosionPrimeEvent;
|
||||
import org.bukkit.event.entity.FoodLevelChangeEvent;
|
||||
import org.bukkit.event.entity.PigZapEvent;
|
||||
import org.bukkit.event.entity.PlayerDeathEvent;
|
||||
import org.bukkit.event.entity.PotionSplashEvent;
|
||||
import org.bukkit.inventory.ItemStack;
|
||||
import org.bukkit.projectiles.ProjectileSource;
|
||||
|
||||
@@ -144,11 +107,6 @@ public class WorldGuardEntityListener implements Listener {
|
||||
} else if (defender instanceof Player) {
|
||||
Player player = (Player) defender;
|
||||
|
||||
if (isInvincible(player)) {
|
||||
event.setCancelled(true);
|
||||
return;
|
||||
}
|
||||
|
||||
if (wcfg.disableLavaDamage && type == DamageCause.LAVA) {
|
||||
event.setCancelled(true);
|
||||
player.setFireTicks(0);
|
||||
@@ -216,17 +174,6 @@ public class WorldGuardEntityListener implements Listener {
|
||||
ConfigurationManager cfg = plugin.getGlobalStateManager();
|
||||
WorldConfiguration wcfg = cfg.get(player.getWorld());
|
||||
|
||||
if (isInvincible(player)) {
|
||||
if (wcfg.regionInvinciblityRemovesMobs
|
||||
&& attacker instanceof LivingEntity && !(attacker instanceof Player)
|
||||
&& !(attacker instanceof Tameable && ((Tameable) attacker).isTamed())) {
|
||||
attacker.remove();
|
||||
}
|
||||
|
||||
event.setCancelled(true);
|
||||
return;
|
||||
}
|
||||
|
||||
if (wcfg.disableLightningDamage && event.getCause() == DamageCause.LIGHTNING) {
|
||||
event.setCancelled(true);
|
||||
return;
|
||||
@@ -322,12 +269,6 @@ public class WorldGuardEntityListener implements Listener {
|
||||
ConfigurationManager cfg = plugin.getGlobalStateManager();
|
||||
WorldConfiguration wcfg = cfg.get(player.getWorld());
|
||||
|
||||
// Check Invincible
|
||||
if (isInvincible(player)) {
|
||||
event.setCancelled(true);
|
||||
return;
|
||||
}
|
||||
|
||||
// Check Mob
|
||||
if (attacker != null && !(attacker instanceof Player)) {
|
||||
if (wcfg.disableMobDamage) {
|
||||
@@ -375,12 +316,6 @@ public class WorldGuardEntityListener implements Listener {
|
||||
} else if (defender instanceof Player) {
|
||||
Player player = (Player) defender;
|
||||
|
||||
if (isInvincible(player)) {
|
||||
event.setCancelled(true);
|
||||
player.setFireTicks(0);
|
||||
return;
|
||||
}
|
||||
|
||||
if (type == DamageCause.WITHER) {
|
||||
// wither boss DoT tick
|
||||
if (wcfg.disableMobDamage) {
|
||||
@@ -445,23 +380,6 @@ public class WorldGuardEntityListener implements Listener {
|
||||
}
|
||||
}
|
||||
|
||||
@EventHandler(priority = EventPriority.HIGH, ignoreCancelled = true)
|
||||
public void onEntityCombust(EntityCombustEvent event) {
|
||||
Entity entity = event.getEntity();
|
||||
|
||||
ConfigurationManager cfg = plugin.getGlobalStateManager();
|
||||
WorldConfiguration wcfg = cfg.get(entity.getWorld());
|
||||
|
||||
if (entity instanceof Player) {
|
||||
Player player = (Player) entity;
|
||||
|
||||
if (cfg.hasGodMode(player) || (wcfg.useRegions && RegionQueryUtil.isInvincible(plugin, player))) {
|
||||
event.setCancelled(true);
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Called on entity explode.
|
||||
*/
|
||||
@@ -635,6 +553,11 @@ public class WorldGuardEntityListener implements Listener {
|
||||
return;
|
||||
}
|
||||
|
||||
// armor stands are living entities, but we check them as blocks/non-living entities, so ignore them here
|
||||
if (Entities.isConsideredBuildingIfUsed(event.getEntity())) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (wcfg.allowTamedSpawns
|
||||
&& event.getEntity() instanceof Tameable // nullsafe check
|
||||
&& ((Tameable) event.getEntity()).isTamed()) {
|
||||
@@ -758,45 +681,6 @@ public class WorldGuardEntityListener implements Listener {
|
||||
}
|
||||
}
|
||||
|
||||
@EventHandler(priority = EventPriority.HIGH, ignoreCancelled = true)
|
||||
public void onFoodLevelChange(FoodLevelChangeEvent event) {
|
||||
if (event.getEntity() instanceof Player) {
|
||||
Player player = (Player) event.getEntity();
|
||||
if (event.getFoodLevel() < player.getFoodLevel() && isInvincible(player)) {
|
||||
event.setCancelled(true);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Check if a player is invincible, via either god mode or region flag. If
|
||||
* the region denies invincibility, the player must have an extra permission
|
||||
* to override it. (worldguard.god.override-regions)
|
||||
*
|
||||
* @param player The player to check
|
||||
* @return Whether {@code player} is invincible
|
||||
*/
|
||||
private boolean isInvincible(Player player) {
|
||||
ConfigurationManager cfg = plugin.getGlobalStateManager();
|
||||
WorldConfiguration wcfg = cfg.get(player.getWorld());
|
||||
|
||||
boolean god = cfg.hasGodMode(player);
|
||||
if (wcfg.useRegions) {
|
||||
Boolean flag = RegionQueryUtil.isAllowedInvinciblity(plugin, player);
|
||||
boolean allowed = flag == null || flag;
|
||||
boolean invincible = RegionQueryUtil.isInvincible(plugin, player);
|
||||
|
||||
if (allowed) {
|
||||
return god || invincible;
|
||||
} else {
|
||||
return (god && plugin.hasPermission(player, "worldguard.god.override-regions"))
|
||||
|| invincible;
|
||||
}
|
||||
} else {
|
||||
return god;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks regions and config settings to protect items from being knocked
|
||||
* out of item frames.
|
||||
|
||||
@@ -26,11 +26,13 @@ import com.sk89q.worldguard.bukkit.ConfigurationManager;
|
||||
import com.sk89q.worldguard.bukkit.WorldConfiguration;
|
||||
import com.sk89q.worldguard.bukkit.WorldGuardPlugin;
|
||||
import com.sk89q.worldguard.bukkit.event.player.ProcessPlayerEvent;
|
||||
import com.sk89q.worldguard.bukkit.listener.FlagStateManager.PlayerFlagState;
|
||||
import com.sk89q.worldguard.bukkit.util.Events;
|
||||
import com.sk89q.worldguard.protection.ApplicableRegionSet;
|
||||
import com.sk89q.worldguard.protection.flags.DefaultFlag;
|
||||
import com.sk89q.worldguard.protection.regions.ProtectedRegion;
|
||||
import com.sk89q.worldguard.session.MoveType;
|
||||
import com.sk89q.worldguard.session.Session;
|
||||
import com.sk89q.worldguard.session.handler.GameModeFlag;
|
||||
import com.sk89q.worldguard.util.command.CommandFilter;
|
||||
import org.bukkit.ChatColor;
|
||||
import org.bukkit.GameMode;
|
||||
@@ -83,11 +85,15 @@ public class WorldGuardPlayerListener implements Listener {
|
||||
public void onPlayerGameModeChange(PlayerGameModeChangeEvent event) {
|
||||
Player player = event.getPlayer();
|
||||
WorldConfiguration wcfg = plugin.getGlobalStateManager().get(player.getWorld());
|
||||
if (wcfg.useRegions && !plugin.getGlobalRegionManager().hasBypass(player, player.getWorld())) {
|
||||
GameMode gameMode = plugin.getRegionContainer().createQuery().getApplicableRegions(player.getLocation()).getFlag(DefaultFlag.GAME_MODE);
|
||||
if (plugin.getFlagStateManager().getState(player).lastGameMode != null
|
||||
&& gameMode != null && event.getNewGameMode() != gameMode) {
|
||||
event.setCancelled(true);
|
||||
Session session = plugin.getSessionManager().getIfPresent(player);
|
||||
if (session != null) {
|
||||
GameModeFlag handler = session.getHandler(GameModeFlag.class);
|
||||
if (handler != null && wcfg.useRegions && !plugin.getGlobalRegionManager().hasBypass(player, player.getWorld())) {
|
||||
GameMode expected = handler.getSetGameMode();
|
||||
if (handler.getOriginalGameMode() != null && expected != null && expected != event.getNewGameMode()) {
|
||||
log.info("Game mode change on " + player.getName() + " has been blocked due to the region GAMEMODE flag");
|
||||
event.setCancelled(true);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -126,14 +132,7 @@ public class WorldGuardPlayerListener implements Listener {
|
||||
|
||||
Events.fire(new ProcessPlayerEvent(player));
|
||||
|
||||
if (wcfg.useRegions) {
|
||||
PlayerFlagState state = plugin.getFlagStateManager().getState(player);
|
||||
Location loc = player.getLocation();
|
||||
state.lastWorld = loc.getWorld();
|
||||
state.lastBlockX = loc.getBlockX();
|
||||
state.lastBlockY = loc.getBlockY();
|
||||
state.lastBlockZ = loc.getBlockZ();
|
||||
}
|
||||
plugin.getSessionManager().get(player); // Initializes a session
|
||||
}
|
||||
|
||||
@EventHandler(ignoreCancelled = true)
|
||||
@@ -186,46 +185,6 @@ public class WorldGuardPlayerListener implements Listener {
|
||||
}
|
||||
}
|
||||
|
||||
@EventHandler
|
||||
public void onPlayerQuit(PlayerQuitEvent event) {
|
||||
Player player = event.getPlayer();
|
||||
World world = player.getWorld();
|
||||
|
||||
ConfigurationManager cfg = plugin.getGlobalStateManager();
|
||||
WorldConfiguration wcfg = cfg.get(world);
|
||||
|
||||
// This is to make the enter/exit flags accurate -- move events are not
|
||||
// sent constantly, so it is possible to move just a little enough to
|
||||
// not trigger the event and then rejoin so that you are then considered
|
||||
// outside the border. This should work around that.
|
||||
if (wcfg.useRegions) {
|
||||
boolean hasBypass = plugin.getGlobalRegionManager().hasBypass(player, world);
|
||||
PlayerFlagState state = plugin.getFlagStateManager().getState(player);
|
||||
|
||||
if (state.lastWorld != null && !hasBypass) {
|
||||
LocalPlayer localPlayer = plugin.wrapPlayer(player);
|
||||
Location loc = player.getLocation();
|
||||
ApplicableRegionSet set = plugin.getRegionContainer().createQuery().getApplicableRegions(loc);
|
||||
|
||||
if (state.lastExitAllowed == null) {
|
||||
state.lastExitAllowed = set.allows(DefaultFlag.EXIT, localPlayer);
|
||||
}
|
||||
|
||||
if (!state.lastExitAllowed || !set.allows(DefaultFlag.ENTRY, localPlayer)) {
|
||||
// Only if we have the last location cached
|
||||
if (state.lastWorld.equals(world)) {
|
||||
Location newLoc = new Location(world, state.lastBlockX + 0.5,
|
||||
state.lastBlockY, state.lastBlockZ + 0.5);
|
||||
player.teleport(newLoc);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
cfg.forgetPlayer(plugin.wrapPlayer(player));
|
||||
plugin.forgetPlayer(player);
|
||||
}
|
||||
|
||||
@EventHandler(priority = EventPriority.HIGH)
|
||||
public void onPlayerInteract(PlayerInteractEvent event) {
|
||||
Player player = event.getPlayer();
|
||||
@@ -378,20 +337,20 @@ public class WorldGuardPlayerListener implements Listener {
|
||||
}
|
||||
}
|
||||
|
||||
@EventHandler(priority= EventPriority.LOW, ignoreCancelled = true)
|
||||
@EventHandler(priority = EventPriority.LOW, ignoreCancelled = true)
|
||||
public void onPlayerTeleport(PlayerTeleportEvent event) {
|
||||
World world = event.getFrom().getWorld();
|
||||
Player player = event.getPlayer();
|
||||
ConfigurationManager cfg = plugin.getGlobalStateManager();
|
||||
WorldConfiguration wcfg = cfg.get(world);
|
||||
|
||||
if (wcfg.useRegions) {
|
||||
ApplicableRegionSet set = plugin.getRegionContainer().createQuery().getApplicableRegions(event.getTo());
|
||||
ApplicableRegionSet setFrom = plugin.getRegionContainer().createQuery().getApplicableRegions(event.getFrom());
|
||||
LocalPlayer localPlayer = plugin.wrapPlayer(event.getPlayer());
|
||||
LocalPlayer localPlayer = plugin.wrapPlayer(player);
|
||||
|
||||
if (cfg.usePlayerTeleports) {
|
||||
boolean result = plugin.getPlayerMoveListener().shouldDenyMove(event.getPlayer(), event.getFrom(), event.getTo());
|
||||
if (result) {
|
||||
if (null != plugin.getSessionManager().get(player).testMoveTo(player, event.getTo(), MoveType.TELEPORT)) {
|
||||
event.setCancelled(true);
|
||||
return;
|
||||
}
|
||||
@@ -401,7 +360,7 @@ public class WorldGuardPlayerListener implements Listener {
|
||||
if (!plugin.getGlobalRegionManager().hasBypass(localPlayer, world)
|
||||
&& !(set.allows(DefaultFlag.ENDERPEARL, localPlayer)
|
||||
&& setFrom.allows(DefaultFlag.ENDERPEARL, localPlayer))) {
|
||||
event.getPlayer().sendMessage(ChatColor.DARK_RED + "You're not allowed to go there.");
|
||||
player.sendMessage(ChatColor.DARK_RED + "You're not allowed to go there.");
|
||||
event.setCancelled(true);
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -22,12 +22,15 @@ package com.sk89q.worldguard.bukkit.listener;
|
||||
import com.sk89q.worldguard.bukkit.ConfigurationManager;
|
||||
import com.sk89q.worldguard.bukkit.WorldConfiguration;
|
||||
import com.sk89q.worldguard.bukkit.WorldGuardPlugin;
|
||||
import com.sk89q.worldguard.bukkit.util.Locations;
|
||||
import com.sk89q.worldguard.session.MoveType;
|
||||
import org.bukkit.World;
|
||||
import org.bukkit.entity.Player;
|
||||
import org.bukkit.entity.Vehicle;
|
||||
import org.bukkit.event.EventHandler;
|
||||
import org.bukkit.event.Listener;
|
||||
import org.bukkit.event.vehicle.VehicleMoveEvent;
|
||||
import org.bukkit.util.Vector;
|
||||
|
||||
public class WorldGuardVehicleListener implements Listener {
|
||||
|
||||
@@ -52,8 +55,7 @@ public class WorldGuardVehicleListener implements Listener {
|
||||
@EventHandler
|
||||
public void onVehicleMove(VehicleMoveEvent event) {
|
||||
Vehicle vehicle = event.getVehicle();
|
||||
if (vehicle.getPassenger() == null
|
||||
|| !(vehicle.getPassenger() instanceof Player)) return;
|
||||
if (vehicle.getPassenger() == null || !(vehicle.getPassenger() instanceof Player)) return;
|
||||
Player player = (Player) vehicle.getPassenger();
|
||||
World world = vehicle.getWorld();
|
||||
ConfigurationManager cfg = plugin.getGlobalStateManager();
|
||||
@@ -61,12 +63,9 @@ public class WorldGuardVehicleListener implements Listener {
|
||||
|
||||
if (wcfg.useRegions) {
|
||||
// Did we move a block?
|
||||
if (event.getFrom().getBlockX() != event.getTo().getBlockX()
|
||||
|| event.getFrom().getBlockY() != event.getTo().getBlockY()
|
||||
|| event.getFrom().getBlockZ() != event.getTo().getBlockZ()) {
|
||||
boolean result = plugin.getPlayerMoveListener().shouldDenyMove(player, event.getFrom(), event.getTo());
|
||||
if (result) {
|
||||
vehicle.setVelocity(new org.bukkit.util.Vector(0,0,0));
|
||||
if (Locations.isDifferentBlock(event.getFrom(), event.getTo())) {
|
||||
if (null != plugin.getSessionManager().get(player).testMoveTo(player, event.getTo(), MoveType.RIDE)) {
|
||||
vehicle.setVelocity(new Vector(0,0,0));
|
||||
vehicle.teleport(event.getFrom());
|
||||
}
|
||||
}
|
||||
|
||||
@@ -27,6 +27,8 @@ import org.bukkit.World;
|
||||
import org.bukkit.command.CommandSender;
|
||||
import org.bukkit.entity.Player;
|
||||
|
||||
import javax.annotation.Nullable;
|
||||
|
||||
/**
|
||||
* Used for querying region-related permissions.
|
||||
*/
|
||||
@@ -117,13 +119,30 @@ public class RegionPermissionModel extends AbstractPermissionModel {
|
||||
public boolean maySetFlag(ProtectedRegion region) {
|
||||
return hasPatternPermission("flag.regions", region);
|
||||
}
|
||||
|
||||
|
||||
public boolean maySetFlag(ProtectedRegion region, Flag<?> flag) {
|
||||
// This is a WTF permission
|
||||
return hasPatternPermission(
|
||||
"flag.flags." + flag.getName().toLowerCase(), region);
|
||||
}
|
||||
|
||||
public boolean maySetFlag(ProtectedRegion region, Flag<?> flag, @Nullable String value) {
|
||||
String sanitizedValue;
|
||||
|
||||
if (value != null) {
|
||||
sanitizedValue = value.trim().toLowerCase().replaceAll("[^a-z0-9]", "");
|
||||
if (sanitizedValue.length() > 20) {
|
||||
sanitizedValue = sanitizedValue.substring(0, 20);
|
||||
}
|
||||
} else {
|
||||
sanitizedValue = "unset";
|
||||
}
|
||||
|
||||
// This is a WTF permission
|
||||
return hasPatternPermission(
|
||||
"flag.flags." + flag.getName().toLowerCase() + "." + sanitizedValue, region);
|
||||
}
|
||||
|
||||
public boolean mayAddMembers(ProtectedRegion region) {
|
||||
return hasPatternPermission("addmember", region);
|
||||
}
|
||||
|
||||
+9
-6
@@ -27,6 +27,7 @@ import com.sk89q.worldguard.protection.regions.ProtectedRegion;
|
||||
import org.bukkit.Location;
|
||||
|
||||
import javax.annotation.Nullable;
|
||||
import java.util.List;
|
||||
import java.util.Set;
|
||||
|
||||
import static com.google.common.base.Preconditions.checkNotNull;
|
||||
@@ -36,7 +37,7 @@ import static com.google.common.base.Preconditions.checkNotNull;
|
||||
* region is in a set of source regions.
|
||||
*
|
||||
* <p>This class only performs a spatial query if its
|
||||
* {@link #getAssociation(ProtectedRegion)} method is called.</p>
|
||||
* {@link #getAssociation(List)} method is called.</p>
|
||||
*/
|
||||
public class DelayedRegionOverlapAssociation implements RegionAssociable {
|
||||
|
||||
@@ -59,17 +60,19 @@ public class DelayedRegionOverlapAssociation implements RegionAssociable {
|
||||
}
|
||||
|
||||
@Override
|
||||
public Association getAssociation(ProtectedRegion region) {
|
||||
public Association getAssociation(List<ProtectedRegion> regions) {
|
||||
if (source == null) {
|
||||
ApplicableRegionSet result = query.getApplicableRegions(location);
|
||||
source = result.getRegions();
|
||||
}
|
||||
|
||||
if ((region.getId().equals(ProtectedRegion.GLOBAL_REGION) && source.isEmpty()) || source.contains(region)) {
|
||||
return Association.OWNER;
|
||||
} else {
|
||||
return Association.NON_MEMBER;
|
||||
for (ProtectedRegion region : regions) {
|
||||
if ((region.getId().equals(ProtectedRegion.GLOBAL_REGION) && source.isEmpty()) || source.contains(region)) {
|
||||
return Association.OWNER;
|
||||
}
|
||||
}
|
||||
|
||||
return Association.NON_MEMBER;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -20,9 +20,13 @@
|
||||
package com.sk89q.worldguard.bukkit.util;
|
||||
|
||||
import org.bukkit.block.Block;
|
||||
import org.bukkit.block.BlockFace;
|
||||
import org.bukkit.block.BlockState;
|
||||
import org.bukkit.material.Bed;
|
||||
import org.bukkit.material.Chest;
|
||||
import org.bukkit.material.MaterialData;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
@@ -43,7 +47,8 @@ public final class Blocks {
|
||||
* @return a list of connected blocks, not including the given block
|
||||
*/
|
||||
public static List<Block> getConnected(Block block) {
|
||||
MaterialData data = block.getState().getData();
|
||||
BlockState state = block.getState();
|
||||
MaterialData data = state.getData();
|
||||
|
||||
if (data instanceof Bed) {
|
||||
Bed bed = (Bed) data;
|
||||
@@ -52,6 +57,28 @@ public final class Blocks {
|
||||
} else {
|
||||
return Arrays.asList(block.getRelative(bed.getFacing()));
|
||||
}
|
||||
} else if (data instanceof Chest) {
|
||||
BlockFace facing = ((Chest) data).getFacing();
|
||||
ArrayList<Block> chests = new ArrayList<Block>();
|
||||
if (facing == BlockFace.NORTH || facing == BlockFace.SOUTH) {
|
||||
if (block.getRelative(BlockFace.EAST).getState().getData() instanceof Chest) {
|
||||
chests.add(block.getRelative(BlockFace.EAST));
|
||||
}
|
||||
if (block.getRelative(BlockFace.WEST).getState().getData() instanceof Chest) {
|
||||
chests.add(block.getRelative(BlockFace.WEST));
|
||||
}
|
||||
} else if (facing == BlockFace.EAST || facing == BlockFace.WEST) {
|
||||
if (block.getRelative(BlockFace.NORTH).getState().getData() instanceof Chest) {
|
||||
chests.add(block.getRelative(BlockFace.NORTH));
|
||||
}
|
||||
if (block.getRelative(BlockFace.SOUTH).getState().getData() instanceof Chest) {
|
||||
chests.add(block.getRelative(BlockFace.SOUTH));
|
||||
}
|
||||
} else {
|
||||
// don't know how to handle diagonal chests
|
||||
return Collections.emptyList();
|
||||
}
|
||||
return chests;
|
||||
} else {
|
||||
return Collections.emptyList();
|
||||
}
|
||||
|
||||
@@ -19,6 +19,7 @@
|
||||
|
||||
package com.sk89q.worldguard.bukkit.util;
|
||||
|
||||
import com.sk89q.worldguard.util.Enums;
|
||||
import org.bukkit.entity.*;
|
||||
import org.bukkit.entity.minecart.ExplosiveMinecart;
|
||||
import org.bukkit.projectiles.ProjectileSource;
|
||||
@@ -119,18 +120,6 @@ public final class Entities {
|
||||
return entity;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return whether the given player is a fake player using the typical
|
||||
* fake player convention of [Mod].
|
||||
*
|
||||
* @param player the player
|
||||
* @return true if a fake player
|
||||
*/
|
||||
public static boolean isFakePlayer(Player player) {
|
||||
String name = player.getName();
|
||||
return name.length() >= 3 && name.charAt(0) == '[' && name.charAt(name.length() - 1) == ']';
|
||||
}
|
||||
|
||||
/**
|
||||
* Test whether an entity is hostile.
|
||||
*
|
||||
@@ -144,6 +133,17 @@ public final class Entities {
|
||||
|| entity instanceof EnderDragon;
|
||||
}
|
||||
|
||||
/**
|
||||
* Test whether an entity is a non-hostile creature.
|
||||
*
|
||||
* @param entity
|
||||
* @return true if non-hostile
|
||||
*/
|
||||
public static boolean isNonHostile(Entity entity) {
|
||||
return !isHostile(entity)
|
||||
&& (entity instanceof Creature || entity instanceof WaterMob);
|
||||
}
|
||||
|
||||
/**
|
||||
* Test whether an entity is ambient.
|
||||
*
|
||||
@@ -161,7 +161,7 @@ public final class Entities {
|
||||
* @return true if an NPC
|
||||
*/
|
||||
public static boolean isNPC(Entity entity) {
|
||||
return entity instanceof NPC;
|
||||
return entity instanceof NPC || entity.hasMetadata("NPC");
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -175,6 +175,9 @@ public final class Entities {
|
||||
return entity instanceof LivingEntity && !(entity instanceof Player);
|
||||
}
|
||||
|
||||
private static final org.bukkit.entity.EntityType armorStandType =
|
||||
Enums.findByValue(org.bukkit.entity.EntityType.class, "ARMOR_STAND");
|
||||
|
||||
/**
|
||||
* Test whether using the given entity should be considered "building"
|
||||
* rather than merely using an entity.
|
||||
@@ -183,7 +186,8 @@ public final class Entities {
|
||||
* @return true if considered building
|
||||
*/
|
||||
public static boolean isConsideredBuildingIfUsed(Entity entity) {
|
||||
return entity instanceof Hanging;
|
||||
return entity instanceof Hanging
|
||||
|| entity.getType() == armorStandType;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -110,7 +110,7 @@ public final class Events {
|
||||
*/
|
||||
public static <T extends Event & Cancellable & BulkEvent> boolean fireBulkEventToCancel(Cancellable original, T eventToFire) {
|
||||
Bukkit.getServer().getPluginManager().callEvent(eventToFire);
|
||||
if (eventToFire.isExplicitlyCancelled()) {
|
||||
if (eventToFire.getExplicitResult() == Result.DENY) {
|
||||
original.setCancelled(true);
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -0,0 +1,116 @@
|
||||
/*
|
||||
* WorldGuard, a suite of tools for Minecraft
|
||||
* Copyright (C) sk89q <http://www.sk89q.com>
|
||||
* Copyright (C) WorldGuard team and contributors
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify it
|
||||
* under the terms of the GNU Lesser General Public License as published by the
|
||||
* Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License
|
||||
* for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
package com.sk89q.worldguard.bukkit.util;
|
||||
|
||||
import com.google.common.base.Function;
|
||||
import org.bukkit.Bukkit;
|
||||
import org.bukkit.entity.Player;
|
||||
|
||||
import javax.annotation.Nullable;
|
||||
import java.lang.reflect.Method;
|
||||
import java.util.UUID;
|
||||
import java.util.logging.Level;
|
||||
import java.util.logging.Logger;
|
||||
|
||||
public final class InteropUtils {
|
||||
|
||||
@Nullable
|
||||
private static final Class<?> forgeFakePlayerClass;
|
||||
// This UUID is from Minecraft Forge (see FakePlayerFactory)
|
||||
private static final UUID forgeFakePlayerUuid = UUID.fromString("41c82c87-7afb-4024-ba57-13d2c99cae77");
|
||||
private static final PlayerHandleFunction playerHandleFunction;
|
||||
|
||||
static {
|
||||
forgeFakePlayerClass = findClass("net.minecraftforge.common.util.FakePlayer");
|
||||
|
||||
PlayerHandleFunction function;
|
||||
try {
|
||||
function = new PlayerHandleFunction();
|
||||
} catch (Exception e) {
|
||||
function = null;
|
||||
}
|
||||
playerHandleFunction = function;
|
||||
}
|
||||
|
||||
@Nullable
|
||||
private static Class<?> findClass(String name) {
|
||||
try {
|
||||
return Class.forName(name);
|
||||
} catch (Throwable ignored) {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
private InteropUtils() {
|
||||
}
|
||||
|
||||
/**
|
||||
* Return whether the given player is a fake player.
|
||||
*
|
||||
* @param player the player
|
||||
* @return true if a fake player
|
||||
*/
|
||||
public static boolean isFakePlayer(Player player) {
|
||||
UUID uuid = player.getUniqueId();
|
||||
String name = player.getName();
|
||||
|
||||
if (uuid.equals(forgeFakePlayerUuid)) {
|
||||
return true;
|
||||
}
|
||||
|
||||
if (forgeFakePlayerClass != null && playerHandleFunction != null) {
|
||||
Object handle = playerHandleFunction.apply(player);
|
||||
if (handle != null) {
|
||||
if (forgeFakePlayerClass.isAssignableFrom(handle.getClass())) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (name.length() >= 3 && name.charAt(0) == '[' && name.charAt(name.length() - 1) == ']') {
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
private static final class PlayerHandleFunction implements Function<Object, Object> {
|
||||
private final Class<?> craftPlayerClass;
|
||||
private final Method getHandleMethod;
|
||||
|
||||
private PlayerHandleFunction() throws NoSuchMethodException, ClassNotFoundException {
|
||||
craftPlayerClass = Class.forName(Bukkit.getServer().getClass().getCanonicalName().replaceAll("CraftServer$", "entity.CraftPlayer"));
|
||||
getHandleMethod = craftPlayerClass.getMethod("getHandle");
|
||||
}
|
||||
|
||||
@Nullable
|
||||
@Override
|
||||
public Object apply(Object o) {
|
||||
if (craftPlayerClass.isAssignableFrom(o.getClass())) {
|
||||
try {
|
||||
return getHandleMethod.invoke(o);
|
||||
} catch (Throwable ignored) {
|
||||
}
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,40 @@
|
||||
/*
|
||||
* WorldGuard, a suite of tools for Minecraft
|
||||
* Copyright (C) sk89q <http://www.sk89q.com>
|
||||
* Copyright (C) WorldGuard team and contributors
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify it
|
||||
* under the terms of the GNU Lesser General Public License as published by the
|
||||
* Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License
|
||||
* for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
package com.sk89q.worldguard.bukkit.util;
|
||||
|
||||
import org.bukkit.Location;
|
||||
|
||||
public final class Locations {
|
||||
|
||||
private Locations() {
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests whether two different locations are in two different blocks.
|
||||
*
|
||||
* @param a The first location
|
||||
* @param b The second location
|
||||
* @return Whether the two locations are two different blocks
|
||||
*/
|
||||
public static boolean isDifferentBlock(Location a, Location b) {
|
||||
return a.getBlockX() != b.getBlockX() || a.getBlockY() != b.getBlockY() || a.getBlockZ() != b.getBlockZ();
|
||||
}
|
||||
|
||||
}
|
||||
@@ -38,14 +38,23 @@ import java.util.*;
|
||||
*/
|
||||
public final class Materials {
|
||||
|
||||
private static final int MODIFIED_ON_CLICK = 1;
|
||||
private static final int MODIFIES_BLOCKS = 2;
|
||||
private static final int MODIFIED_ON_RIGHT = 1;
|
||||
private static final int MODIFIED_ON_LEFT = 2;
|
||||
private static final int MODIFIES_BLOCKS = 4;
|
||||
|
||||
private static final BiMap<EntityType, Material> ENTITY_ITEMS = HashBiMap.create();
|
||||
private static final Map<Material, Integer> MATERIAL_FLAGS = new HashMap<Material, Integer>();
|
||||
private static final Set<PotionEffectType> DAMAGE_EFFECTS = new HashSet<PotionEffectType>();
|
||||
|
||||
public static Material ARMOR_STAND;
|
||||
|
||||
static {
|
||||
try {
|
||||
ARMOR_STAND = Material.ARMOR_STAND;
|
||||
} catch (NoSuchFieldError ignored) {
|
||||
ARMOR_STAND = null;
|
||||
}
|
||||
|
||||
ENTITY_ITEMS.put(EntityType.PAINTING, Material.PAINTING);
|
||||
ENTITY_ITEMS.put(EntityType.ARROW, Material.ARROW);
|
||||
ENTITY_ITEMS.put(EntityType.SNOWBALL, Material.SNOW_BALL);
|
||||
@@ -65,6 +74,9 @@ public final class Materials {
|
||||
ENTITY_ITEMS.put(EntityType.MINECART_HOPPER, Material.HOPPER_MINECART);
|
||||
ENTITY_ITEMS.put(EntityType.SPLASH_POTION, Material.POTION);
|
||||
ENTITY_ITEMS.put(EntityType.EGG, Material.EGG);
|
||||
try {
|
||||
ENTITY_ITEMS.put(EntityType.ARMOR_STAND, Material.ARMOR_STAND);
|
||||
} catch (NoSuchFieldError ignored) {}
|
||||
|
||||
MATERIAL_FLAGS.put(Material.AIR, 0);
|
||||
MATERIAL_FLAGS.put(Material.STONE, 0);
|
||||
@@ -89,10 +101,10 @@ public final class Materials {
|
||||
MATERIAL_FLAGS.put(Material.GLASS, 0);
|
||||
MATERIAL_FLAGS.put(Material.LAPIS_ORE, 0);
|
||||
MATERIAL_FLAGS.put(Material.LAPIS_BLOCK, 0);
|
||||
MATERIAL_FLAGS.put(Material.DISPENSER, MODIFIED_ON_CLICK);
|
||||
MATERIAL_FLAGS.put(Material.DISPENSER, MODIFIED_ON_RIGHT);
|
||||
MATERIAL_FLAGS.put(Material.SANDSTONE, 0);
|
||||
MATERIAL_FLAGS.put(Material.NOTE_BLOCK, MODIFIED_ON_CLICK);
|
||||
MATERIAL_FLAGS.put(Material.BED_BLOCK, MODIFIED_ON_CLICK);
|
||||
MATERIAL_FLAGS.put(Material.NOTE_BLOCK, MODIFIED_ON_RIGHT);
|
||||
MATERIAL_FLAGS.put(Material.BED_BLOCK, MODIFIED_ON_RIGHT);
|
||||
MATERIAL_FLAGS.put(Material.POWERED_RAIL, 0);
|
||||
MATERIAL_FLAGS.put(Material.DETECTOR_RAIL, 0);
|
||||
MATERIAL_FLAGS.put(Material.PISTON_STICKY_BASE, 0);
|
||||
@@ -112,7 +124,7 @@ public final class Materials {
|
||||
MATERIAL_FLAGS.put(Material.DOUBLE_STEP, 0);
|
||||
MATERIAL_FLAGS.put(Material.STEP, 0);
|
||||
MATERIAL_FLAGS.put(Material.BRICK, 0);
|
||||
MATERIAL_FLAGS.put(Material.TNT, MODIFIED_ON_CLICK);
|
||||
MATERIAL_FLAGS.put(Material.TNT, MODIFIED_ON_RIGHT);
|
||||
MATERIAL_FLAGS.put(Material.BOOKSHELF, 0);
|
||||
MATERIAL_FLAGS.put(Material.MOSSY_COBBLESTONE, 0);
|
||||
MATERIAL_FLAGS.put(Material.OBSIDIAN, 0);
|
||||
@@ -120,37 +132,37 @@ public final class Materials {
|
||||
MATERIAL_FLAGS.put(Material.FIRE, 0);
|
||||
MATERIAL_FLAGS.put(Material.MOB_SPAWNER, 0);
|
||||
MATERIAL_FLAGS.put(Material.WOOD_STAIRS, 0);
|
||||
MATERIAL_FLAGS.put(Material.CHEST, MODIFIED_ON_CLICK);
|
||||
MATERIAL_FLAGS.put(Material.CHEST, MODIFIED_ON_RIGHT);
|
||||
MATERIAL_FLAGS.put(Material.REDSTONE_WIRE, 0);
|
||||
MATERIAL_FLAGS.put(Material.DIAMOND_ORE, 0);
|
||||
MATERIAL_FLAGS.put(Material.DIAMOND_BLOCK, 0);
|
||||
MATERIAL_FLAGS.put(Material.WORKBENCH, MODIFIED_ON_CLICK);
|
||||
MATERIAL_FLAGS.put(Material.WORKBENCH, MODIFIED_ON_RIGHT);
|
||||
MATERIAL_FLAGS.put(Material.CROPS, 0);
|
||||
MATERIAL_FLAGS.put(Material.SOIL, 0);
|
||||
MATERIAL_FLAGS.put(Material.FURNACE, MODIFIED_ON_CLICK);
|
||||
MATERIAL_FLAGS.put(Material.BURNING_FURNACE, MODIFIED_ON_CLICK);
|
||||
MATERIAL_FLAGS.put(Material.FURNACE, MODIFIED_ON_RIGHT);
|
||||
MATERIAL_FLAGS.put(Material.BURNING_FURNACE, MODIFIED_ON_RIGHT);
|
||||
MATERIAL_FLAGS.put(Material.SIGN_POST, 0);
|
||||
MATERIAL_FLAGS.put(Material.WOODEN_DOOR, MODIFIED_ON_CLICK);
|
||||
MATERIAL_FLAGS.put(Material.WOODEN_DOOR, MODIFIED_ON_RIGHT);
|
||||
MATERIAL_FLAGS.put(Material.LADDER, 0);
|
||||
MATERIAL_FLAGS.put(Material.RAILS, 0);
|
||||
MATERIAL_FLAGS.put(Material.COBBLESTONE_STAIRS, 0);
|
||||
MATERIAL_FLAGS.put(Material.WALL_SIGN, 0);
|
||||
MATERIAL_FLAGS.put(Material.LEVER, MODIFIED_ON_CLICK);
|
||||
MATERIAL_FLAGS.put(Material.LEVER, MODIFIED_ON_RIGHT);
|
||||
MATERIAL_FLAGS.put(Material.STONE_PLATE, 0);
|
||||
MATERIAL_FLAGS.put(Material.IRON_DOOR_BLOCK, MODIFIED_ON_CLICK);
|
||||
MATERIAL_FLAGS.put(Material.IRON_DOOR_BLOCK, 0);
|
||||
MATERIAL_FLAGS.put(Material.WOOD_PLATE, 0);
|
||||
MATERIAL_FLAGS.put(Material.REDSTONE_ORE, 0);
|
||||
MATERIAL_FLAGS.put(Material.GLOWING_REDSTONE_ORE, 0);
|
||||
MATERIAL_FLAGS.put(Material.REDSTONE_TORCH_OFF, 0);
|
||||
MATERIAL_FLAGS.put(Material.REDSTONE_TORCH_ON, 0);
|
||||
MATERIAL_FLAGS.put(Material.STONE_BUTTON, MODIFIED_ON_CLICK);
|
||||
MATERIAL_FLAGS.put(Material.STONE_BUTTON, MODIFIED_ON_RIGHT);
|
||||
MATERIAL_FLAGS.put(Material.SNOW, 0);
|
||||
MATERIAL_FLAGS.put(Material.ICE, 0);
|
||||
MATERIAL_FLAGS.put(Material.SNOW_BLOCK, 0);
|
||||
MATERIAL_FLAGS.put(Material.CACTUS, 0);
|
||||
MATERIAL_FLAGS.put(Material.CLAY, 0);
|
||||
MATERIAL_FLAGS.put(Material.SUGAR_CANE_BLOCK, 0);
|
||||
MATERIAL_FLAGS.put(Material.JUKEBOX, MODIFIED_ON_CLICK);
|
||||
MATERIAL_FLAGS.put(Material.JUKEBOX, MODIFIED_ON_RIGHT);
|
||||
MATERIAL_FLAGS.put(Material.FENCE, 0);
|
||||
MATERIAL_FLAGS.put(Material.PUMPKIN, 0);
|
||||
MATERIAL_FLAGS.put(Material.NETHERRACK, 0);
|
||||
@@ -158,11 +170,11 @@ public final class Materials {
|
||||
MATERIAL_FLAGS.put(Material.GLOWSTONE, 0);
|
||||
MATERIAL_FLAGS.put(Material.PORTAL, 0);
|
||||
MATERIAL_FLAGS.put(Material.JACK_O_LANTERN, 0);
|
||||
MATERIAL_FLAGS.put(Material.CAKE_BLOCK, MODIFIED_ON_CLICK);
|
||||
MATERIAL_FLAGS.put(Material.DIODE_BLOCK_OFF, MODIFIED_ON_CLICK);
|
||||
MATERIAL_FLAGS.put(Material.DIODE_BLOCK_ON, MODIFIED_ON_CLICK);
|
||||
MATERIAL_FLAGS.put(Material.CAKE_BLOCK, MODIFIED_ON_RIGHT);
|
||||
MATERIAL_FLAGS.put(Material.DIODE_BLOCK_OFF, MODIFIED_ON_RIGHT);
|
||||
MATERIAL_FLAGS.put(Material.DIODE_BLOCK_ON, MODIFIED_ON_RIGHT);
|
||||
MATERIAL_FLAGS.put(Material.STAINED_GLASS, 0);
|
||||
MATERIAL_FLAGS.put(Material.TRAP_DOOR, MODIFIED_ON_CLICK);
|
||||
MATERIAL_FLAGS.put(Material.TRAP_DOOR, MODIFIED_ON_RIGHT);
|
||||
MATERIAL_FLAGS.put(Material.MONSTER_EGGS, 0);
|
||||
MATERIAL_FLAGS.put(Material.SMOOTH_BRICK, 0);
|
||||
MATERIAL_FLAGS.put(Material.HUGE_MUSHROOM_1, 0);
|
||||
@@ -173,7 +185,7 @@ public final class Materials {
|
||||
MATERIAL_FLAGS.put(Material.PUMPKIN_STEM, 0);
|
||||
MATERIAL_FLAGS.put(Material.MELON_STEM, 0);
|
||||
MATERIAL_FLAGS.put(Material.VINE, 0);
|
||||
MATERIAL_FLAGS.put(Material.FENCE_GATE, MODIFIED_ON_CLICK);
|
||||
MATERIAL_FLAGS.put(Material.FENCE_GATE, MODIFIED_ON_RIGHT);
|
||||
MATERIAL_FLAGS.put(Material.BRICK_STAIRS, 0);
|
||||
MATERIAL_FLAGS.put(Material.SMOOTH_STAIRS, 0);
|
||||
MATERIAL_FLAGS.put(Material.MYCEL, 0);
|
||||
@@ -182,13 +194,13 @@ public final class Materials {
|
||||
MATERIAL_FLAGS.put(Material.NETHER_FENCE, 0);
|
||||
MATERIAL_FLAGS.put(Material.NETHER_BRICK_STAIRS, 0);
|
||||
MATERIAL_FLAGS.put(Material.NETHER_WARTS, 0);
|
||||
MATERIAL_FLAGS.put(Material.ENCHANTMENT_TABLE, MODIFIED_ON_CLICK);
|
||||
MATERIAL_FLAGS.put(Material.BREWING_STAND, MODIFIED_ON_CLICK);
|
||||
MATERIAL_FLAGS.put(Material.CAULDRON, MODIFIED_ON_CLICK);
|
||||
MATERIAL_FLAGS.put(Material.ENCHANTMENT_TABLE, MODIFIED_ON_RIGHT);
|
||||
MATERIAL_FLAGS.put(Material.BREWING_STAND, MODIFIED_ON_RIGHT);
|
||||
MATERIAL_FLAGS.put(Material.CAULDRON, MODIFIED_ON_RIGHT);
|
||||
MATERIAL_FLAGS.put(Material.ENDER_PORTAL, 0);
|
||||
MATERIAL_FLAGS.put(Material.ENDER_PORTAL_FRAME, 0);
|
||||
MATERIAL_FLAGS.put(Material.ENDER_STONE, 0);
|
||||
MATERIAL_FLAGS.put(Material.DRAGON_EGG, MODIFIED_ON_CLICK);
|
||||
MATERIAL_FLAGS.put(Material.DRAGON_EGG, MODIFIED_ON_LEFT | MODIFIED_ON_RIGHT);
|
||||
MATERIAL_FLAGS.put(Material.REDSTONE_LAMP_OFF, 0);
|
||||
MATERIAL_FLAGS.put(Material.REDSTONE_LAMP_ON, 0);
|
||||
MATERIAL_FLAGS.put(Material.WOOD_DOUBLE_STEP, 0);
|
||||
@@ -196,35 +208,35 @@ public final class Materials {
|
||||
MATERIAL_FLAGS.put(Material.COCOA, 0);
|
||||
MATERIAL_FLAGS.put(Material.SANDSTONE_STAIRS, 0);
|
||||
MATERIAL_FLAGS.put(Material.EMERALD_ORE, 0);
|
||||
MATERIAL_FLAGS.put(Material.ENDER_CHEST, 0);
|
||||
MATERIAL_FLAGS.put(Material.ENDER_CHEST, MODIFIED_ON_RIGHT);
|
||||
MATERIAL_FLAGS.put(Material.TRIPWIRE_HOOK, 0);
|
||||
MATERIAL_FLAGS.put(Material.TRIPWIRE, 0);
|
||||
MATERIAL_FLAGS.put(Material.EMERALD_BLOCK, 0);
|
||||
MATERIAL_FLAGS.put(Material.SPRUCE_WOOD_STAIRS, 0);
|
||||
MATERIAL_FLAGS.put(Material.BIRCH_WOOD_STAIRS, 0);
|
||||
MATERIAL_FLAGS.put(Material.JUNGLE_WOOD_STAIRS, 0);
|
||||
MATERIAL_FLAGS.put(Material.COMMAND, MODIFIED_ON_CLICK);
|
||||
MATERIAL_FLAGS.put(Material.BEACON, MODIFIED_ON_CLICK);
|
||||
MATERIAL_FLAGS.put(Material.COMMAND, MODIFIED_ON_RIGHT);
|
||||
MATERIAL_FLAGS.put(Material.BEACON, MODIFIED_ON_RIGHT);
|
||||
MATERIAL_FLAGS.put(Material.COBBLE_WALL, 0);
|
||||
MATERIAL_FLAGS.put(Material.FLOWER_POT, MODIFIED_ON_CLICK);
|
||||
MATERIAL_FLAGS.put(Material.FLOWER_POT, MODIFIED_ON_RIGHT);
|
||||
MATERIAL_FLAGS.put(Material.CARROT, 0);
|
||||
MATERIAL_FLAGS.put(Material.POTATO, 0);
|
||||
MATERIAL_FLAGS.put(Material.WOOD_BUTTON, MODIFIED_ON_CLICK);
|
||||
MATERIAL_FLAGS.put(Material.WOOD_BUTTON, MODIFIED_ON_RIGHT);
|
||||
MATERIAL_FLAGS.put(Material.SKULL, 0);
|
||||
MATERIAL_FLAGS.put(Material.ANVIL, MODIFIED_ON_CLICK);
|
||||
MATERIAL_FLAGS.put(Material.TRAPPED_CHEST, MODIFIED_ON_CLICK);
|
||||
MATERIAL_FLAGS.put(Material.ANVIL, MODIFIED_ON_RIGHT);
|
||||
MATERIAL_FLAGS.put(Material.TRAPPED_CHEST, MODIFIED_ON_RIGHT);
|
||||
MATERIAL_FLAGS.put(Material.GOLD_PLATE, 0);
|
||||
MATERIAL_FLAGS.put(Material.IRON_PLATE, 0);
|
||||
MATERIAL_FLAGS.put(Material.REDSTONE_COMPARATOR_OFF, MODIFIED_ON_CLICK);
|
||||
MATERIAL_FLAGS.put(Material.REDSTONE_COMPARATOR_ON, MODIFIED_ON_CLICK);
|
||||
MATERIAL_FLAGS.put(Material.DAYLIGHT_DETECTOR, MODIFIED_ON_CLICK);
|
||||
MATERIAL_FLAGS.put(Material.REDSTONE_COMPARATOR_OFF, MODIFIED_ON_RIGHT);
|
||||
MATERIAL_FLAGS.put(Material.REDSTONE_COMPARATOR_ON, MODIFIED_ON_RIGHT);
|
||||
MATERIAL_FLAGS.put(Material.DAYLIGHT_DETECTOR, MODIFIED_ON_RIGHT);
|
||||
MATERIAL_FLAGS.put(Material.REDSTONE_BLOCK, 0);
|
||||
MATERIAL_FLAGS.put(Material.QUARTZ_ORE, 0);
|
||||
MATERIAL_FLAGS.put(Material.HOPPER, MODIFIED_ON_CLICK);
|
||||
MATERIAL_FLAGS.put(Material.HOPPER, MODIFIED_ON_RIGHT);
|
||||
MATERIAL_FLAGS.put(Material.QUARTZ_BLOCK, 0);
|
||||
MATERIAL_FLAGS.put(Material.QUARTZ_STAIRS, 0);
|
||||
MATERIAL_FLAGS.put(Material.ACTIVATOR_RAIL, 0);
|
||||
MATERIAL_FLAGS.put(Material.DROPPER, MODIFIED_ON_CLICK);
|
||||
MATERIAL_FLAGS.put(Material.DROPPER, MODIFIED_ON_RIGHT);
|
||||
MATERIAL_FLAGS.put(Material.STAINED_CLAY, 0);
|
||||
MATERIAL_FLAGS.put(Material.STAINED_GLASS_PANE, 0);
|
||||
MATERIAL_FLAGS.put(Material.LEAVES_2, 0);
|
||||
@@ -237,6 +249,31 @@ public final class Materials {
|
||||
MATERIAL_FLAGS.put(Material.COAL_BLOCK, 0);
|
||||
MATERIAL_FLAGS.put(Material.PACKED_ICE, 0);
|
||||
MATERIAL_FLAGS.put(Material.DOUBLE_PLANT, 0);
|
||||
try {
|
||||
MATERIAL_FLAGS.put(Material.STANDING_BANNER, 0);
|
||||
MATERIAL_FLAGS.put(Material.WALL_BANNER, 0);
|
||||
MATERIAL_FLAGS.put(Material.DAYLIGHT_DETECTOR_INVERTED, MODIFIED_ON_RIGHT);
|
||||
MATERIAL_FLAGS.put(Material.RED_SANDSTONE, 0);
|
||||
MATERIAL_FLAGS.put(Material.RED_SANDSTONE_STAIRS, 0);
|
||||
MATERIAL_FLAGS.put(Material.DOUBLE_STONE_SLAB2, 0);
|
||||
MATERIAL_FLAGS.put(Material.STONE_SLAB2, 0);
|
||||
MATERIAL_FLAGS.put(Material.SPRUCE_FENCE_GATE, MODIFIED_ON_RIGHT);
|
||||
MATERIAL_FLAGS.put(Material.BIRCH_FENCE_GATE, MODIFIED_ON_RIGHT);
|
||||
MATERIAL_FLAGS.put(Material.JUNGLE_FENCE_GATE, MODIFIED_ON_RIGHT);
|
||||
MATERIAL_FLAGS.put(Material.DARK_OAK_FENCE_GATE, MODIFIED_ON_RIGHT);
|
||||
MATERIAL_FLAGS.put(Material.ACACIA_FENCE_GATE, MODIFIED_ON_RIGHT);
|
||||
MATERIAL_FLAGS.put(Material.SPRUCE_FENCE, 0);
|
||||
MATERIAL_FLAGS.put(Material.BIRCH_FENCE, 0);
|
||||
MATERIAL_FLAGS.put(Material.JUNGLE_FENCE, 0);
|
||||
MATERIAL_FLAGS.put(Material.DARK_OAK_FENCE, 0);
|
||||
MATERIAL_FLAGS.put(Material.ACACIA_FENCE, 0);
|
||||
MATERIAL_FLAGS.put(Material.SPRUCE_DOOR, MODIFIED_ON_RIGHT);
|
||||
MATERIAL_FLAGS.put(Material.BIRCH_DOOR, MODIFIED_ON_RIGHT);
|
||||
MATERIAL_FLAGS.put(Material.JUNGLE_DOOR, MODIFIED_ON_RIGHT);
|
||||
MATERIAL_FLAGS.put(Material.ACACIA_DOOR, MODIFIED_ON_RIGHT);
|
||||
MATERIAL_FLAGS.put(Material.DARK_OAK_DOOR, MODIFIED_ON_RIGHT);
|
||||
} catch (NoSuchFieldError ignored) {
|
||||
}
|
||||
|
||||
MATERIAL_FLAGS.put(Material.IRON_SPADE, 0);
|
||||
MATERIAL_FLAGS.put(Material.IRON_PICKAXE, 0);
|
||||
@@ -365,7 +402,7 @@ public final class Materials {
|
||||
MATERIAL_FLAGS.put(Material.CAULDRON_ITEM, 0);
|
||||
MATERIAL_FLAGS.put(Material.EYE_OF_ENDER, 0);
|
||||
MATERIAL_FLAGS.put(Material.SPECKLED_MELON, 0);
|
||||
MATERIAL_FLAGS.put(Material.MONSTER_EGG, 0);
|
||||
MATERIAL_FLAGS.put(Material.MONSTER_EGG, MODIFIES_BLOCKS);
|
||||
MATERIAL_FLAGS.put(Material.EXP_BOTTLE, 0);
|
||||
MATERIAL_FLAGS.put(Material.FIREBALL, 0);
|
||||
MATERIAL_FLAGS.put(Material.BOOK_AND_QUILL, 0);
|
||||
@@ -397,6 +434,28 @@ public final class Materials {
|
||||
MATERIAL_FLAGS.put(Material.LEASH, 0);
|
||||
MATERIAL_FLAGS.put(Material.NAME_TAG, 0);
|
||||
MATERIAL_FLAGS.put(Material.COMMAND_MINECART, 0);
|
||||
try {
|
||||
MATERIAL_FLAGS.put(Material.PRISMARINE_SHARD, 0);
|
||||
MATERIAL_FLAGS.put(Material.PRISMARINE_CRYSTALS, 0);
|
||||
MATERIAL_FLAGS.put(Material.RABBIT, 0);
|
||||
MATERIAL_FLAGS.put(Material.COOKED_RABBIT, 0);
|
||||
MATERIAL_FLAGS.put(Material.RABBIT_STEW, 0);
|
||||
MATERIAL_FLAGS.put(Material.RABBIT_FOOT, 0);
|
||||
MATERIAL_FLAGS.put(Material.RABBIT_HIDE, 0);
|
||||
MATERIAL_FLAGS.put(Material.ARMOR_STAND, 0);
|
||||
MATERIAL_FLAGS.put(Material.IRON_BARDING, 0);
|
||||
MATERIAL_FLAGS.put(Material.GOLD_BARDING, 0);
|
||||
MATERIAL_FLAGS.put(Material.DIAMOND_BARDING, 0);;
|
||||
MATERIAL_FLAGS.put(Material.MUTTON, 0);
|
||||
MATERIAL_FLAGS.put(Material.COOKED_MUTTON, 0);
|
||||
MATERIAL_FLAGS.put(Material.BANNER, 0);
|
||||
MATERIAL_FLAGS.put(Material.SPRUCE_DOOR_ITEM, 0);
|
||||
MATERIAL_FLAGS.put(Material.BIRCH_DOOR_ITEM, 0);
|
||||
MATERIAL_FLAGS.put(Material.JUNGLE_DOOR_ITEM, 0);
|
||||
MATERIAL_FLAGS.put(Material.ACACIA_DOOR_ITEM, 0);
|
||||
MATERIAL_FLAGS.put(Material.DARK_OAK_DOOR_ITEM, 0);
|
||||
} catch (NoSuchFieldError ignored) {
|
||||
}
|
||||
MATERIAL_FLAGS.put(Material.GOLD_RECORD, 0);
|
||||
MATERIAL_FLAGS.put(Material.GREEN_RECORD, 0);
|
||||
MATERIAL_FLAGS.put(Material.RECORD_3, 0);
|
||||
@@ -614,19 +673,35 @@ public final class Materials {
|
||||
* @return true if covered by the use flag
|
||||
*/
|
||||
public static boolean isUseFlagApplicable(Material material) {
|
||||
return material == Material.LEVER
|
||||
|| material == Material.STONE_BUTTON
|
||||
|| material == Material.WOOD_BUTTON
|
||||
|| material == Material.WOODEN_DOOR
|
||||
|| material == Material.TRAP_DOOR
|
||||
|| material == Material.FENCE_GATE
|
||||
|| material == Material.WORKBENCH
|
||||
|| material == Material.ENCHANTMENT_TABLE
|
||||
|| material == Material.BEACON
|
||||
|| material == Material.ANVIL
|
||||
|| material == Material.STONE_PLATE
|
||||
|| material == Material.IRON_PLATE
|
||||
|| material == Material.GOLD_PLATE;
|
||||
switch (material) {
|
||||
case LEVER: return true;
|
||||
case STONE_BUTTON: return true;
|
||||
case WOOD_BUTTON: return true;
|
||||
case TRIPWIRE: return true;
|
||||
case WOODEN_DOOR: return true;
|
||||
case TRAP_DOOR: return true;
|
||||
case FENCE_GATE: return true;
|
||||
case WORKBENCH: return true;
|
||||
case ENCHANTMENT_TABLE: return true;
|
||||
case ENDER_CHEST: return true;
|
||||
case BEACON: return true;
|
||||
case ANVIL: return true;
|
||||
case WOOD_PLATE: return true;
|
||||
case STONE_PLATE: return true;
|
||||
case IRON_PLATE: return true;
|
||||
case GOLD_PLATE: return true;
|
||||
case SPRUCE_FENCE_GATE: return true;
|
||||
case BIRCH_FENCE_GATE: return true;
|
||||
case JUNGLE_FENCE_GATE: return true;
|
||||
case DARK_OAK_FENCE_GATE: return true;
|
||||
case ACACIA_FENCE_GATE: return true;
|
||||
case SPRUCE_DOOR: return true;
|
||||
case BIRCH_DOOR: return true;
|
||||
case JUNGLE_DOOR: return true;
|
||||
case ACACIA_DOOR: return true;
|
||||
case DARK_OAK_DOOR: return true;
|
||||
default: return false;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -647,11 +722,14 @@ public final class Materials {
|
||||
* aware of.</p>
|
||||
*
|
||||
* @param material the material
|
||||
* @param rightClick whether it is a right click
|
||||
* @return true if the block is modified
|
||||
*/
|
||||
public static boolean isBlockModifiedOnClick(Material material) {
|
||||
public static boolean isBlockModifiedOnClick(Material material, boolean rightClick) {
|
||||
Integer flags = MATERIAL_FLAGS.get(material);
|
||||
return flags == null || (flags & MODIFIED_ON_CLICK) == MODIFIED_ON_CLICK;
|
||||
return flags == null
|
||||
|| (rightClick && (flags & MODIFIED_ON_RIGHT) == MODIFIED_ON_RIGHT)
|
||||
|| (!rightClick && (flags & MODIFIED_ON_LEFT) == MODIFIED_ON_LEFT);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -677,7 +755,11 @@ public final class Materials {
|
||||
* @return true to be considered as used
|
||||
*/
|
||||
public static boolean isConsideredBuildingIfUsed(Material type) {
|
||||
return type == Material.SAPLING;
|
||||
return type == Material.SAPLING
|
||||
|| type == Material.DIODE_BLOCK_OFF
|
||||
|| type == Material.DIODE_BLOCK_ON
|
||||
|| type == Material.REDSTONE_COMPARATOR_OFF
|
||||
|| type == Material.REDSTONE_COMPARATOR_ON;
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -19,14 +19,36 @@
|
||||
|
||||
package com.sk89q.worldguard.bukkit.util.report;
|
||||
|
||||
import com.google.common.base.Optional;
|
||||
import com.google.common.reflect.TypeToken;
|
||||
import com.sk89q.guavabackport.cache.CacheBuilder;
|
||||
import com.sk89q.guavabackport.cache.CacheLoader;
|
||||
import com.sk89q.guavabackport.cache.LoadingCache;
|
||||
import com.sk89q.worldguard.util.report.DataReport;
|
||||
import org.bukkit.Bukkit;
|
||||
import org.bukkit.scheduler.BukkitTask;
|
||||
|
||||
import javax.annotation.Nullable;
|
||||
import java.lang.reflect.Field;
|
||||
import java.util.List;
|
||||
import java.util.Set;
|
||||
|
||||
public class SchedulerReport extends DataReport {
|
||||
|
||||
private LoadingCache<Class<?>, Optional<Field>> taskFieldCache = CacheBuilder.newBuilder()
|
||||
.build(new CacheLoader<Class<?>, Optional<Field>>() {
|
||||
@Override
|
||||
public Optional<Field> load(Class<?> clazz) throws Exception {
|
||||
try {
|
||||
Field field = clazz.getDeclaredField("task");
|
||||
field.setAccessible(true);
|
||||
return Optional.fromNullable(field);
|
||||
} catch (NoSuchFieldException ignored) {
|
||||
return Optional.absent();
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
public SchedulerReport() {
|
||||
super("Scheduler");
|
||||
|
||||
@@ -35,10 +57,34 @@ public class SchedulerReport extends DataReport {
|
||||
append("Pending Task Count", tasks.size());
|
||||
|
||||
for (BukkitTask task : tasks) {
|
||||
Class<?> taskClass = getTaskClass(task);
|
||||
|
||||
DataReport report = new DataReport("Task: #" + task.getTaskId());
|
||||
report.append("Owner", task.getOwner().getName());
|
||||
report.append("Runnable", taskClass != null ? taskClass.getName() : "<Unknown>");
|
||||
report.append("Synchronous?", task.isSync());
|
||||
append(report.getTitle(), report);
|
||||
}
|
||||
}
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
@Nullable
|
||||
private Class<?> getTaskClass(BukkitTask task) {
|
||||
try {
|
||||
Class<?> clazz = task.getClass();
|
||||
Set<Class<?>> classes = (Set) TypeToken.of(clazz).getTypes().rawTypes();
|
||||
|
||||
for (Class<?> type : classes) {
|
||||
Optional<Field> field = taskFieldCache.getUnchecked(type);
|
||||
if (field.isPresent()) {
|
||||
Object res = field.get().get(task);
|
||||
return res == null ? null : res.getClass();
|
||||
}
|
||||
}
|
||||
} catch (IllegalAccessException ignored) {
|
||||
} catch (NoClassDefFoundError ignored) {
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
}
|
||||
@@ -19,6 +19,7 @@
|
||||
|
||||
package com.sk89q.worldguard.bukkit.util.report;
|
||||
|
||||
import com.sk89q.worldguard.bukkit.BukkitUtil;
|
||||
import com.sk89q.worldguard.util.report.DataReport;
|
||||
import org.bukkit.Bukkit;
|
||||
import org.bukkit.Server;
|
||||
@@ -34,7 +35,9 @@ public class ServerReport extends DataReport {
|
||||
append("Server Name", server.getServerName());
|
||||
append("Bukkit Version", server.getBukkitVersion());
|
||||
append("Implementation", server.getVersion());
|
||||
append("Player Count", "%d/%d", server.getOnlinePlayers().size(), server.getMaxPlayers());
|
||||
append("Player Count", "%d/%d", BukkitUtil.getOnlinePlayers().size(), server.getMaxPlayers());
|
||||
|
||||
append("Server Class Source", server.getClass().getProtectionDomain().getCodeSource().getLocation());
|
||||
|
||||
DataReport spawning = new DataReport("Spawning");
|
||||
spawning.append("Ambient Spawn Limit", server.getAmbientSpawnLimit());
|
||||
|
||||
@@ -43,6 +43,22 @@ public class DefaultDomain implements Domain, ChangeTracked {
|
||||
private PlayerDomain playerDomain = new PlayerDomain();
|
||||
private GroupDomain groupDomain = new GroupDomain();
|
||||
|
||||
/**
|
||||
* Create a new domain.
|
||||
*/
|
||||
public DefaultDomain() {
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a new domain from an existing one, making a copy of all values.
|
||||
*
|
||||
* @param existing the other domain to copy values from
|
||||
*/
|
||||
public DefaultDomain(DefaultDomain existing) {
|
||||
setPlayerDomain(existing.getPlayerDomain());
|
||||
setGroupDomain(existing.getGroupDomain());
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the domain that holds the players.
|
||||
*
|
||||
@@ -59,7 +75,7 @@ public class DefaultDomain implements Domain, ChangeTracked {
|
||||
*/
|
||||
public void setPlayerDomain(PlayerDomain playerDomain) {
|
||||
checkNotNull(playerDomain);
|
||||
this.playerDomain = playerDomain;
|
||||
this.playerDomain = new PlayerDomain(playerDomain);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -78,7 +94,7 @@ public class DefaultDomain implements Domain, ChangeTracked {
|
||||
*/
|
||||
public void setGroupDomain(GroupDomain groupDomain) {
|
||||
checkNotNull(groupDomain);
|
||||
this.groupDomain = groupDomain;
|
||||
this.groupDomain = new GroupDomain(groupDomain);
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -43,6 +43,16 @@ public class GroupDomain implements Domain, ChangeTracked {
|
||||
public GroupDomain() {
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a new instance with copies from another domain.
|
||||
*
|
||||
* @param domain the domain to copy values from
|
||||
*/
|
||||
public GroupDomain(GroupDomain domain) {
|
||||
checkNotNull(domain, "domain");
|
||||
groups.addAll(domain.getGroups());
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a new instance.
|
||||
*
|
||||
@@ -117,6 +127,7 @@ public class GroupDomain implements Domain, ChangeTracked {
|
||||
|
||||
@Override
|
||||
public void clear() {
|
||||
setDirty(true);
|
||||
groups.clear();
|
||||
}
|
||||
|
||||
|
||||
@@ -44,6 +44,18 @@ public class PlayerDomain implements Domain, ChangeTracked {
|
||||
public PlayerDomain() {
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a new instance.
|
||||
*
|
||||
* @param domain the domain to copy values from
|
||||
*/
|
||||
public PlayerDomain(PlayerDomain domain) {
|
||||
checkNotNull(domain, "domain");
|
||||
uniqueIds.addAll(domain.getUniqueIds());
|
||||
names.addAll(domain.getPlayers());
|
||||
dirty = true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a new instance with the given names.
|
||||
*
|
||||
@@ -113,6 +125,7 @@ public class PlayerDomain implements Domain, ChangeTracked {
|
||||
*/
|
||||
public void removePlayer(UUID uuid) {
|
||||
checkNotNull(uuid);
|
||||
setDirty(true);
|
||||
uniqueIds.remove(uuid);
|
||||
}
|
||||
|
||||
@@ -124,6 +137,7 @@ public class PlayerDomain implements Domain, ChangeTracked {
|
||||
*/
|
||||
public void removePlayer(LocalPlayer player) {
|
||||
checkNotNull(player);
|
||||
setDirty(true);
|
||||
removePlayer(player.getName());
|
||||
removePlayer(player.getUniqueId());
|
||||
}
|
||||
@@ -171,6 +185,7 @@ public class PlayerDomain implements Domain, ChangeTracked {
|
||||
|
||||
@Override
|
||||
public void clear() {
|
||||
setDirty(true);
|
||||
uniqueIds.clear();
|
||||
names.clear();
|
||||
}
|
||||
|
||||
@@ -21,6 +21,7 @@ package com.sk89q.worldguard.protection;
|
||||
|
||||
import com.google.common.collect.ImmutableList;
|
||||
import com.google.common.collect.Iterables;
|
||||
import com.google.common.collect.Sets;
|
||||
import com.sk89q.worldguard.domains.Association;
|
||||
import com.sk89q.worldguard.protection.association.RegionAssociable;
|
||||
import com.sk89q.worldguard.protection.flags.DefaultFlag;
|
||||
@@ -29,15 +30,10 @@ import com.sk89q.worldguard.protection.flags.RegionGroup;
|
||||
import com.sk89q.worldguard.protection.flags.StateFlag;
|
||||
import com.sk89q.worldguard.protection.flags.StateFlag.State;
|
||||
import com.sk89q.worldguard.protection.regions.ProtectedRegion;
|
||||
import com.sk89q.worldguard.protection.util.NormativeOrders;
|
||||
|
||||
import javax.annotation.Nullable;
|
||||
import java.util.Arrays;
|
||||
import java.util.Collection;
|
||||
import java.util.HashMap;
|
||||
import java.util.HashSet;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
import java.util.*;
|
||||
|
||||
import static com.google.common.base.Preconditions.checkNotNull;
|
||||
|
||||
@@ -61,7 +57,7 @@ public class FlagValueCalculator {
|
||||
/**
|
||||
* Create a new instance.
|
||||
*
|
||||
* @param regions a list of applicable regions that <strong>must be sorted by priority descending</strong>
|
||||
* @param regions a list of applicable regions that must be sorted according to {@link NormativeOrders}
|
||||
* @param globalRegion an optional global region (null to not use one)
|
||||
*/
|
||||
public FlagValueCalculator(List<ProtectedRegion> regions, @Nullable ProtectedRegion globalRegion) {
|
||||
@@ -108,36 +104,9 @@ public class FlagValueCalculator {
|
||||
checkNotNull(subject);
|
||||
|
||||
int minimumPriority = Integer.MIN_VALUE;
|
||||
boolean foundApplicableRegion = false;
|
||||
Result result = Result.NO_REGIONS;
|
||||
|
||||
// Say there are two regions in one location: CHILD and PARENT (CHILD
|
||||
// is a child of PARENT). If there are two overlapping regions in WG, a
|
||||
// subject has to be a member of /both/ (or flags permit) in order to
|
||||
// build in that location. However, inheritance is supposed
|
||||
// to allow building if the subject is a member of just CHILD. That
|
||||
// presents a problem.
|
||||
//
|
||||
// To rectify this, we keep two sets. When we iterate over the list of
|
||||
// regions, there are two scenarios that we may encounter:
|
||||
//
|
||||
// 1) PARENT first, CHILD later:
|
||||
// a) When the loop reaches PARENT, PARENT is added to needsClear.
|
||||
// b) When the loop reaches CHILD, parents of CHILD (which includes
|
||||
// PARENT) are removed from needsClear.
|
||||
// c) needsClear is empty again.
|
||||
//
|
||||
// 2) CHILD first, PARENT later:
|
||||
// a) When the loop reaches CHILD, CHILD's parents (i.e. PARENT) are
|
||||
// added to hasCleared.
|
||||
// b) When the loop reaches PARENT, since PARENT is already in
|
||||
// hasCleared, it does not add PARENT to needsClear.
|
||||
// c) needsClear stays empty.
|
||||
//
|
||||
// As long as the process ends with needsClear being empty, then
|
||||
// we have satisfied all membership requirements.
|
||||
|
||||
Set<ProtectedRegion> needsClear = new HashSet<ProtectedRegion>();
|
||||
Set<ProtectedRegion> hasCleared = new HashSet<ProtectedRegion>();
|
||||
Set<ProtectedRegion> ignoredRegions = Sets.newHashSet();
|
||||
|
||||
for (ProtectedRegion region : getApplicable()) {
|
||||
// Don't consider lower priorities below minimumPriority
|
||||
@@ -153,24 +122,23 @@ public class FlagValueCalculator {
|
||||
continue;
|
||||
}
|
||||
|
||||
minimumPriority = getPriority(region);
|
||||
foundApplicableRegion = true;
|
||||
if (ignoredRegions.contains(region)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
if (!hasCleared.contains(region)) {
|
||||
if (!RegionGroup.MEMBERS.contains(subject.getAssociation(region))) {
|
||||
needsClear.add(region);
|
||||
} else {
|
||||
// Need to clear all parents
|
||||
removeParents(needsClear, hasCleared, region);
|
||||
}
|
||||
minimumPriority = getPriority(region);
|
||||
|
||||
boolean member = RegionGroup.MEMBERS.contains(subject.getAssociation(Arrays.asList(region)));
|
||||
|
||||
if (member) {
|
||||
result = Result.SUCCESS;
|
||||
addParents(ignoredRegions, region);
|
||||
} else {
|
||||
return Result.FAIL;
|
||||
}
|
||||
}
|
||||
|
||||
if (foundApplicableRegion) {
|
||||
return needsClear.isEmpty() ? Result.SUCCESS : Result.FAIL;
|
||||
} else {
|
||||
return Result.NO_REGIONS;
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
|
||||
@@ -249,7 +217,7 @@ public class FlagValueCalculator {
|
||||
*/
|
||||
@Nullable
|
||||
public <V> V queryValue(@Nullable RegionAssociable subject, Flag<V> flag) {
|
||||
Collection<V> values = queryAllValues(subject, flag);
|
||||
Collection<V> values = queryAllValues(subject, flag, true);
|
||||
return flag.chooseValue(values);
|
||||
}
|
||||
|
||||
@@ -270,85 +238,80 @@ public class FlagValueCalculator {
|
||||
* @param flag the flag
|
||||
* @return a collection of values
|
||||
*/
|
||||
@SuppressWarnings("unchecked")
|
||||
public <V> Collection<V> queryAllValues(@Nullable RegionAssociable subject, Flag<V> flag) {
|
||||
return queryAllValues(subject, flag, false);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the effective values for a flag, returning a collection of all
|
||||
* values. It is up to the caller to determine which value, if any,
|
||||
* from the collection will be used.
|
||||
*
|
||||
* <p>A subject can be provided that is used to determine whether the value
|
||||
* of a flag on a particular region should be used. For example, if a
|
||||
* flag's region group is set to {@link RegionGroup#MEMBERS} and the given
|
||||
* subject is not a member, then the region would be skipped when
|
||||
* querying that flag. If {@code null} is provided for the subject, then
|
||||
* only flags that use {@link RegionGroup#ALL},
|
||||
* {@link RegionGroup#NON_MEMBERS}, etc. will apply.</p>
|
||||
*
|
||||
* @param subject an optional subject, which would be used to determine the region group to apply
|
||||
* @param flag the flag
|
||||
* @param acceptOne if possible, return only one value if it doesn't matter
|
||||
* @return a collection of values
|
||||
*/
|
||||
@SuppressWarnings("unchecked")
|
||||
private <V> Collection<V> queryAllValues(@Nullable RegionAssociable subject, Flag<V> flag, boolean acceptOne) {
|
||||
checkNotNull(flag);
|
||||
|
||||
// Can't use this optimization with flags that have a conflict resolution strategy
|
||||
if (acceptOne && flag.hasConflictStrategy()) {
|
||||
acceptOne = false;
|
||||
}
|
||||
|
||||
// Check to see whether we have a subject if this is BUILD
|
||||
if (flag == DefaultFlag.BUILD && subject == null) {
|
||||
throw new NullPointerException("The BUILD flag is handled in a special fashion and requires a non-null subject parameter");
|
||||
if (flag.requiresSubject() && subject == null) {
|
||||
throw new NullPointerException("The " + flag.getName() + " flag is handled in a special fashion and requires a non-null subject parameter");
|
||||
}
|
||||
|
||||
int minimumPriority = Integer.MIN_VALUE;
|
||||
|
||||
// Say there are two regions in one location: CHILD and PARENT (CHILD
|
||||
// is a child of PARENT). If the two are overlapping regions in WG,
|
||||
// both with values set, then we have a problem. Due to inheritance,
|
||||
// only the CHILD's value for the flag should be used because it
|
||||
// overrides its parent's value, but default behavior is to collect
|
||||
// all the values into a list.
|
||||
//
|
||||
// To rectify this, we keep a map of consideredValues (region -> value)
|
||||
// and an ignoredRegions set. When we iterate over the list of
|
||||
// regions, there are two scenarios that we may encounter:
|
||||
//
|
||||
// 1) PARENT first, CHILD later:
|
||||
// a) When the loop reaches PARENT, PARENT's value is added to
|
||||
// consideredValues
|
||||
// b) When the loop reaches CHILD, parents of CHILD (which includes
|
||||
// PARENT) are removed from consideredValues (so we no longer
|
||||
// consider those values). The CHILD's value is then added to
|
||||
// consideredValues.
|
||||
// c) In the end, only CHILD's value exists in consideredValues.
|
||||
//
|
||||
// 2) CHILD first, PARENT later:
|
||||
// a) When the loop reaches CHILD, CHILD's value is added to
|
||||
// consideredValues. In addition, the CHILD's parents (which
|
||||
// includes PARENT) are added to ignoredRegions.
|
||||
// b) When the loop reaches PARENT, since PARENT is in
|
||||
// ignoredRegions, the parent is skipped over.
|
||||
// c) In the end, only CHILD's value exists in consideredValues.
|
||||
|
||||
Map<ProtectedRegion, V> consideredValues = new HashMap<ProtectedRegion, V>();
|
||||
Set<ProtectedRegion> ignoredRegions = new HashSet<ProtectedRegion>();
|
||||
Set<ProtectedRegion> ignoredParents = new HashSet<ProtectedRegion>();
|
||||
|
||||
for (ProtectedRegion region : getApplicable()) {
|
||||
// Don't consider lower priorities below minimumPriority
|
||||
// (which starts at Integer.MIN_VALUE). A region that "counts"
|
||||
// (has the flag set) will raise minimumPriority to its own
|
||||
// priority.
|
||||
if (getPriority(region) < minimumPriority) {
|
||||
break;
|
||||
}
|
||||
|
||||
if (ignoredParents.contains(region)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
V value = getEffectiveFlag(region, flag, subject);
|
||||
int priority = getPriority(region);
|
||||
|
||||
if (value != null) {
|
||||
if (!ignoredRegions.contains(region)) {
|
||||
minimumPriority = priority;
|
||||
minimumPriority = priority;
|
||||
|
||||
ignoreValuesOfParents(consideredValues, ignoredRegions, region);
|
||||
if (acceptOne) {
|
||||
return Arrays.asList(value);
|
||||
} else {
|
||||
consideredValues.put(region, value);
|
||||
|
||||
if (value == State.DENY) {
|
||||
// Since DENY overrides all other values, there
|
||||
// is no need to consider any further regions
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// The BUILD flag (of lower priorities) can be overridden if
|
||||
// this region has members... this check is here due to legacy
|
||||
// reasons
|
||||
if (priority != minimumPriority && flag == DefaultFlag.BUILD
|
||||
addParents(ignoredParents, region);
|
||||
|
||||
// The BUILD flag is implicitly set on every region where
|
||||
// PASSTHROUGH is not set to ALLOW
|
||||
if (priority != minimumPriority && flag.implicitlySetWithMembership()
|
||||
&& getEffectiveFlag(region, DefaultFlag.PASSTHROUGH, subject) != State.ALLOW) {
|
||||
minimumPriority = getPriority(region);
|
||||
}
|
||||
}
|
||||
|
||||
if (flag == DefaultFlag.BUILD && consideredValues.isEmpty()) {
|
||||
if (flag.usesMembershipAsDefault() && consideredValues.isEmpty()) {
|
||||
switch (getMembership(subject)) {
|
||||
case FAIL:
|
||||
return ImmutableList.of();
|
||||
@@ -401,17 +364,21 @@ public class FlagValueCalculator {
|
||||
return (V) State.ALLOW;
|
||||
}
|
||||
|
||||
} else if (flag == DefaultFlag.BUILD) {
|
||||
} else if (flag instanceof StateFlag && ((StateFlag) flag).preventsAllowOnGlobal()) {
|
||||
// Legacy behavior -> we can't let people change BUILD on
|
||||
// the global region
|
||||
State value = region.getFlag(DefaultFlag.BUILD);
|
||||
State value = region.getFlag((StateFlag) flag);
|
||||
return value != State.ALLOW ? (V) value : null;
|
||||
}
|
||||
}
|
||||
|
||||
ProtectedRegion current = region;
|
||||
|
||||
List<ProtectedRegion> seen = new ArrayList<ProtectedRegion>();
|
||||
|
||||
while (current != null) {
|
||||
seen.add(current);
|
||||
|
||||
V value = current.getFlag(flag);
|
||||
|
||||
if (value != null) {
|
||||
@@ -427,7 +394,7 @@ public class FlagValueCalculator {
|
||||
use = false;
|
||||
} else if (subject == null) {
|
||||
use = group.contains(Association.NON_MEMBER);
|
||||
} else if (!group.contains(subject.getAssociation(region))) {
|
||||
} else if (!group.contains(subject.getAssociation(seen))) {
|
||||
use = false;
|
||||
}
|
||||
}
|
||||
@@ -443,40 +410,17 @@ public class FlagValueCalculator {
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Clear a region's parents for isFlagAllowed().
|
||||
*
|
||||
* @param needsClear the regions that should be cleared
|
||||
* @param hasCleared the regions already cleared
|
||||
* @param region the region to start from
|
||||
*/
|
||||
private void removeParents(Set<ProtectedRegion> needsClear, Set<ProtectedRegion> hasCleared, ProtectedRegion region) {
|
||||
ProtectedRegion parent = region.getParent();
|
||||
|
||||
while (parent != null) {
|
||||
if (!needsClear.remove(parent)) {
|
||||
hasCleared.add(parent);
|
||||
}
|
||||
|
||||
parent = parent.getParent();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Clear a region's parents for getFlag().
|
||||
*
|
||||
* @param needsClear The regions that should be cleared
|
||||
* @param hasCleared The regions already cleared
|
||||
* @param ignored The regions to ignore
|
||||
* @param region The region to start from
|
||||
*/
|
||||
private void ignoreValuesOfParents(Map<ProtectedRegion, ?> needsClear, Set<ProtectedRegion> hasCleared, ProtectedRegion region) {
|
||||
private void addParents(Set<ProtectedRegion> ignored, ProtectedRegion region) {
|
||||
ProtectedRegion parent = region.getParent();
|
||||
|
||||
while (parent != null) {
|
||||
if (needsClear.remove(parent) == null) {
|
||||
hasCleared.add(parent);
|
||||
}
|
||||
|
||||
ignored.add(parent);
|
||||
parent = parent.getParent();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -25,14 +25,10 @@ import com.sk89q.worldguard.protection.flags.Flag;
|
||||
import com.sk89q.worldguard.protection.flags.StateFlag;
|
||||
import com.sk89q.worldguard.protection.flags.StateFlag.State;
|
||||
import com.sk89q.worldguard.protection.regions.ProtectedRegion;
|
||||
import com.sk89q.worldguard.protection.util.NormativeOrders;
|
||||
|
||||
import javax.annotation.Nullable;
|
||||
import java.util.Collection;
|
||||
import java.util.Collections;
|
||||
import java.util.HashSet;
|
||||
import java.util.Iterator;
|
||||
import java.util.List;
|
||||
import java.util.Set;
|
||||
import java.util.*;
|
||||
|
||||
import static com.google.common.base.Preconditions.checkNotNull;
|
||||
|
||||
@@ -47,9 +43,10 @@ public class RegionResultSet extends AbstractRegionSet {
|
||||
private Set<ProtectedRegion> regionSet;
|
||||
|
||||
/**
|
||||
* Construct the object.
|
||||
* Create a new region result set.
|
||||
*
|
||||
* <p>A sorted set will be created to include the collection of regions.</p>
|
||||
* <p>The given list must not contain duplicates or the behavior of
|
||||
* this instance will be undefined.</p>
|
||||
*
|
||||
* @param applicable the regions contained in this set
|
||||
* @param globalRegion the global region, set aside for special handling.
|
||||
@@ -59,16 +56,31 @@ public class RegionResultSet extends AbstractRegionSet {
|
||||
}
|
||||
|
||||
/**
|
||||
* Construct the object.
|
||||
* Create a new region result set.
|
||||
*
|
||||
* @param applicable the regions contained in this set
|
||||
* @param globalRegion the global region, set aside for special handling.
|
||||
*/
|
||||
public RegionResultSet(Set<ProtectedRegion> applicable, @Nullable ProtectedRegion globalRegion) {
|
||||
this(NormativeOrders.fromSet(applicable), globalRegion, true);
|
||||
this.regionSet = applicable;
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a new region result set.
|
||||
*
|
||||
* <p>The list of regions may be first sorted with
|
||||
* {@link NormativeOrders}. If that is the case, {@code sorted} should be
|
||||
* {@code true}. Otherwise, the list will be sorted in-place.</p>
|
||||
*
|
||||
* @param applicable the regions contained in this set
|
||||
* @param globalRegion the global region, set aside for special handling.
|
||||
* @param sorted true if the list is already sorted
|
||||
* @param sorted true if the list is already sorted with {@link NormativeOrders}
|
||||
*/
|
||||
private RegionResultSet(List<ProtectedRegion> applicable, @Nullable ProtectedRegion globalRegion, boolean sorted) {
|
||||
public RegionResultSet(List<ProtectedRegion> applicable, @Nullable ProtectedRegion globalRegion, boolean sorted) {
|
||||
checkNotNull(applicable);
|
||||
if (!sorted) {
|
||||
Collections.sort(applicable);
|
||||
NormativeOrders.sort(applicable);
|
||||
}
|
||||
this.applicable = applicable;
|
||||
this.flagValueCalculator = new FlagValueCalculator(applicable, globalRegion);
|
||||
|
||||
@@ -22,6 +22,8 @@ package com.sk89q.worldguard.protection.association;
|
||||
import com.sk89q.worldguard.domains.Association;
|
||||
import com.sk89q.worldguard.protection.regions.ProtectedRegion;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
class ConstantAssociation implements RegionAssociable {
|
||||
|
||||
private final Association association;
|
||||
@@ -31,7 +33,7 @@ class ConstantAssociation implements RegionAssociable {
|
||||
}
|
||||
|
||||
@Override
|
||||
public Association getAssociation(ProtectedRegion region) {
|
||||
public Association getAssociation(List<ProtectedRegion> regions) {
|
||||
return association;
|
||||
}
|
||||
|
||||
|
||||
@@ -22,17 +22,19 @@ package com.sk89q.worldguard.protection.association;
|
||||
import com.sk89q.worldguard.domains.Association;
|
||||
import com.sk89q.worldguard.protection.regions.ProtectedRegion;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* An object that can have membership in a region.
|
||||
*/
|
||||
public interface RegionAssociable {
|
||||
|
||||
/**
|
||||
* Get the most specific association level for the input region.
|
||||
* Get the highest association level for the input regions.
|
||||
*
|
||||
* @param region the input region
|
||||
* @return the most specific membership level
|
||||
* @param regions a list of regions
|
||||
* @return the highest membership level
|
||||
*/
|
||||
Association getAssociation(ProtectedRegion region);
|
||||
Association getAssociation(List<ProtectedRegion> regions);
|
||||
|
||||
}
|
||||
+8
-5
@@ -22,6 +22,7 @@ package com.sk89q.worldguard.protection.association;
|
||||
import com.sk89q.worldguard.domains.Association;
|
||||
import com.sk89q.worldguard.protection.regions.ProtectedRegion;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.Set;
|
||||
|
||||
import static com.google.common.base.Preconditions.checkNotNull;
|
||||
@@ -45,12 +46,14 @@ public class RegionOverlapAssociation implements RegionAssociable {
|
||||
}
|
||||
|
||||
@Override
|
||||
public Association getAssociation(ProtectedRegion region) {
|
||||
if (source.contains(region)) {
|
||||
return Association.OWNER;
|
||||
} else {
|
||||
return Association.NON_MEMBER;
|
||||
public Association getAssociation(List<ProtectedRegion> regions) {
|
||||
for (ProtectedRegion region : regions) {
|
||||
if ((region.getId().equals(ProtectedRegion.GLOBAL_REGION) && source.isEmpty()) || source.contains(region)) {
|
||||
return Association.OWNER;
|
||||
}
|
||||
}
|
||||
|
||||
return Association.NON_MEMBER;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -24,8 +24,7 @@ import org.bukkit.command.CommandSender;
|
||||
import com.sk89q.worldguard.bukkit.WorldGuardPlugin;
|
||||
|
||||
/**
|
||||
*
|
||||
* @author sk89q
|
||||
* A boolean flag.
|
||||
*/
|
||||
public class BooleanFlag extends Flag<Boolean> {
|
||||
|
||||
@@ -38,8 +37,7 @@ public class BooleanFlag extends Flag<Boolean> {
|
||||
}
|
||||
|
||||
@Override
|
||||
public Boolean parseInput(WorldGuardPlugin plugin, CommandSender sender,
|
||||
String input) throws InvalidFlagFormat {
|
||||
public Boolean parseInput(WorldGuardPlugin plugin, CommandSender sender, String input) throws InvalidFlagFormat {
|
||||
input = input.trim();
|
||||
|
||||
if (input.equalsIgnoreCase("true") || input.equalsIgnoreCase("yes")
|
||||
|
||||
@@ -0,0 +1,52 @@
|
||||
/*
|
||||
* WorldGuard, a suite of tools for Minecraft
|
||||
* Copyright (C) sk89q <http://www.sk89q.com>
|
||||
* Copyright (C) WorldGuard team and contributors
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify it
|
||||
* under the terms of the GNU Lesser General Public License as published by the
|
||||
* Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License
|
||||
* for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
package com.sk89q.worldguard.protection.flags;
|
||||
|
||||
/**
|
||||
* A special implementation of the {@link StateFlag} for
|
||||
* {@link DefaultFlag#BUILD}.
|
||||
*/
|
||||
class BuildFlag extends StateFlag {
|
||||
|
||||
public BuildFlag(String name, boolean def) {
|
||||
super(name, def);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean implicitlySetWithMembership() {
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean usesMembershipAsDefault() {
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean preventsAllowOnGlobal() {
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean requiresSubject() {
|
||||
return true;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -24,8 +24,7 @@ import org.bukkit.command.CommandSender;
|
||||
import com.sk89q.worldguard.bukkit.WorldGuardPlugin;
|
||||
|
||||
/**
|
||||
*
|
||||
* @author sk89q
|
||||
* Stores a command/
|
||||
*/
|
||||
public class CommandStringFlag extends Flag<String> {
|
||||
|
||||
@@ -38,8 +37,7 @@ public class CommandStringFlag extends Flag<String> {
|
||||
}
|
||||
|
||||
@Override
|
||||
public String parseInput(WorldGuardPlugin plugin, CommandSender sender,
|
||||
String input) throws InvalidFlagFormat {
|
||||
public String parseInput(WorldGuardPlugin plugin, CommandSender sender, String input) throws InvalidFlagFormat {
|
||||
input = input.trim();
|
||||
if (!input.startsWith("/")) {
|
||||
input = "/" + input;
|
||||
|
||||
@@ -21,6 +21,7 @@ package com.sk89q.worldguard.protection.flags;
|
||||
|
||||
import org.bukkit.ChatColor;
|
||||
import org.bukkit.GameMode;
|
||||
import org.bukkit.WeatherType;
|
||||
import org.bukkit.entity.EntityType;
|
||||
|
||||
/**
|
||||
@@ -39,7 +40,7 @@ public final class DefaultFlag {
|
||||
public static final RegionGroupFlag CONSTRUCT = new RegionGroupFlag("construct", RegionGroup.MEMBERS);
|
||||
|
||||
// This flag is unlike the others. It forces the checking of region membership
|
||||
public static final StateFlag BUILD = new StateFlag("build", true);
|
||||
public static final StateFlag BUILD = new BuildFlag("build", true);
|
||||
|
||||
// These flags are used in tandem with the BUILD flag - if the player can
|
||||
// build, then the following flags do not need to be checked (although they
|
||||
@@ -48,6 +49,7 @@ public final class DefaultFlag {
|
||||
public static final StateFlag BLOCK_PLACE = new StateFlag("block-place", false);
|
||||
public static final StateFlag USE = new StateFlag("use", false);
|
||||
public static final StateFlag INTERACT = new StateFlag("interact", false);
|
||||
public static final StateFlag DAMAGE_ANIMALS = new StateFlag("damage-animals", false);
|
||||
public static final StateFlag PVP = new StateFlag("pvp", false);
|
||||
public static final StateFlag SLEEP = new StateFlag("sleep", false);
|
||||
public static final StateFlag TNT = new StateFlag("tnt", false);
|
||||
@@ -100,16 +102,25 @@ public final class DefaultFlag {
|
||||
public static final StateFlag ENDERPEARL = new StateFlag("enderpearl", true);
|
||||
public static final StateFlag ENTITY_PAINTING_DESTROY = new StateFlag("entity-painting-destroy", true);
|
||||
public static final StateFlag ENTITY_ITEM_FRAME_DESTROY = new StateFlag("entity-item-frame-destroy", true);
|
||||
public static final StateFlag FALL_DAMAGE = new StateFlag("fall-damage", true);
|
||||
|
||||
// Flags that adjust behaviors that aren't state flags
|
||||
public static final StringFlag DENY_MESSAGE = new StringFlag("deny-message",
|
||||
"" + ChatColor.RED + ChatColor.BOLD + "Hey!" + ChatColor.GRAY + " Sorry, but you can't %what% here.");
|
||||
public static final StringFlag ENTRY_DENY_MESSAGE = new StringFlag("entry-deny-message",
|
||||
"" + ChatColor.RED + ChatColor.BOLD + "Hey!" + ChatColor.GRAY + " You are not permitted to enter this area.");
|
||||
public static final StringFlag EXIT_DENY_MESSAGE = new StringFlag("exit-deny-message",
|
||||
"" + ChatColor.RED + ChatColor.BOLD + "Hey!" + ChatColor.GRAY + " You are not permitted to leave this area.");
|
||||
public static final BooleanFlag EXIT_OVERRIDE = new BooleanFlag("exit-override");
|
||||
public static final StateFlag EXIT_VIA_TELEPORT = new StateFlag("exit-via-teleport", true);
|
||||
public static final StringFlag GREET_MESSAGE = new StringFlag("greeting");
|
||||
public static final StringFlag FAREWELL_MESSAGE = new StringFlag("farewell");
|
||||
public static final BooleanFlag NOTIFY_ENTER = new BooleanFlag("notify-enter");
|
||||
public static final BooleanFlag NOTIFY_LEAVE = new BooleanFlag("notify-leave");
|
||||
public static final SetFlag<EntityType> DENY_SPAWN = new SetFlag<EntityType>("deny-spawn", new EntityTypeFlag(null));
|
||||
public static final EnumFlag<GameMode> GAME_MODE = new EnumFlag<GameMode>("game-mode", GameMode.class);
|
||||
public static final StringFlag TIME_LOCK = new StringFlag("time-lock");
|
||||
public static final EnumFlag<WeatherType> WEATHER_LOCK = new EnumFlag<WeatherType>("weather-lock", WeatherType.class);
|
||||
public static final IntegerFlag HEAL_DELAY = new IntegerFlag("heal-delay");
|
||||
public static final IntegerFlag HEAL_AMOUNT = new IntegerFlag("heal-amount");
|
||||
public static final DoubleFlag MIN_HEAL = new DoubleFlag("heal-min-health");
|
||||
@@ -130,18 +141,19 @@ public final class DefaultFlag {
|
||||
|
||||
public static final Flag<?>[] flagsList = new Flag<?>[] {
|
||||
PASSTHROUGH, BUILD, CONSTRUCT, BLOCK_BREAK, BLOCK_PLACE, PVP, CHEST_ACCESS, PISTONS,
|
||||
TNT, LIGHTER, RIDE, USE, INTERACT, PLACE_VEHICLE, DESTROY_VEHICLE, SLEEP,
|
||||
TNT, LIGHTER, RIDE, USE, INTERACT, PLACE_VEHICLE, DESTROY_VEHICLE, DAMAGE_ANIMALS, SLEEP,
|
||||
MOB_DAMAGE, MOB_SPAWNING, DENY_SPAWN, INVINCIBILITY, EXP_DROPS,
|
||||
CREEPER_EXPLOSION, OTHER_EXPLOSION, ENDERDRAGON_BLOCK_DAMAGE, GHAST_FIREBALL, ENDER_BUILD,
|
||||
DENY_MESSAGE, GREET_MESSAGE, FAREWELL_MESSAGE, NOTIFY_ENTER, NOTIFY_LEAVE,
|
||||
DENY_MESSAGE, ENTRY_DENY_MESSAGE, EXIT_DENY_MESSAGE, EXIT_OVERRIDE, EXIT_VIA_TELEPORT,
|
||||
GREET_MESSAGE, FAREWELL_MESSAGE, NOTIFY_ENTER, NOTIFY_LEAVE,
|
||||
EXIT, ENTRY, LIGHTNING, ENTITY_PAINTING_DESTROY, ENDERPEARL,
|
||||
ENTITY_ITEM_FRAME_DESTROY, ITEM_PICKUP, ITEM_DROP, /*MAX_PLAYERS, MAX_PLAYERS_MESSAGE,*/
|
||||
ENTITY_ITEM_FRAME_DESTROY, FALL_DAMAGE, ITEM_PICKUP, ITEM_DROP, /*MAX_PLAYERS, MAX_PLAYERS_MESSAGE,*/
|
||||
HEAL_AMOUNT, HEAL_DELAY, MIN_HEAL, MAX_HEAL,
|
||||
FEED_DELAY, FEED_AMOUNT, MIN_FOOD, MAX_FOOD,
|
||||
SNOW_FALL, SNOW_MELT, ICE_FORM, ICE_MELT, SOIL_DRY, GAME_MODE,
|
||||
MUSHROOMS, LEAF_DECAY, GRASS_SPREAD, MYCELIUM_SPREAD, VINE_GROWTH,
|
||||
SEND_CHAT, RECEIVE_CHAT, FIRE_SPREAD, LAVA_FIRE, LAVA_FLOW, WATER_FLOW,
|
||||
TELE_LOC, SPAWN_LOC, POTION_SPLASH,
|
||||
TELE_LOC, SPAWN_LOC, POTION_SPLASH, TIME_LOCK, WEATHER_LOCK,
|
||||
BLOCKED_CMDS, ALLOWED_CMDS, PRICE, BUYABLE, ENABLE_SHOP
|
||||
};
|
||||
|
||||
|
||||
@@ -24,8 +24,7 @@ import org.bukkit.command.CommandSender;
|
||||
import com.sk89q.worldguard.bukkit.WorldGuardPlugin;
|
||||
|
||||
/**
|
||||
*
|
||||
* @author sk89q
|
||||
* Stores doubles.
|
||||
*/
|
||||
public class DoubleFlag extends Flag<Double> {
|
||||
|
||||
@@ -38,8 +37,7 @@ public class DoubleFlag extends Flag<Double> {
|
||||
}
|
||||
|
||||
@Override
|
||||
public Double parseInput(WorldGuardPlugin plugin, CommandSender sender,
|
||||
String input) throws InvalidFlagFormat {
|
||||
public Double parseInput(WorldGuardPlugin plugin, CommandSender sender, String input) throws InvalidFlagFormat {
|
||||
input = input.trim();
|
||||
|
||||
try {
|
||||
|
||||
@@ -22,9 +22,7 @@ package com.sk89q.worldguard.protection.flags;
|
||||
import org.bukkit.entity.EntityType;
|
||||
|
||||
/**
|
||||
* Represents an entity type.
|
||||
*
|
||||
* @author sk89q
|
||||
* Stores an entity type.
|
||||
*/
|
||||
public class EntityTypeFlag extends EnumFlag<EntityType> {
|
||||
|
||||
|
||||
@@ -24,8 +24,7 @@ import org.bukkit.command.CommandSender;
|
||||
import com.sk89q.worldguard.bukkit.WorldGuardPlugin;
|
||||
|
||||
/**
|
||||
*
|
||||
* @author sk89q
|
||||
* Stores an enum value.
|
||||
*/
|
||||
public class EnumFlag<T extends Enum<T>> extends Flag<T> {
|
||||
|
||||
@@ -79,8 +78,7 @@ public class EnumFlag<T extends Enum<T>> extends Flag<T> {
|
||||
}
|
||||
|
||||
@Override
|
||||
public T parseInput(WorldGuardPlugin plugin, CommandSender sender,
|
||||
String input) throws InvalidFlagFormat {
|
||||
public T parseInput(WorldGuardPlugin plugin, CommandSender sender, String input) throws InvalidFlagFormat {
|
||||
try {
|
||||
return findValue(input);
|
||||
} catch (IllegalArgumentException e) {
|
||||
|
||||
@@ -20,33 +20,45 @@
|
||||
package com.sk89q.worldguard.protection.flags;
|
||||
|
||||
import com.sk89q.worldguard.bukkit.WorldGuardPlugin;
|
||||
import com.sk89q.worldguard.protection.FlagValueCalculator;
|
||||
import org.bukkit.command.CommandSender;
|
||||
|
||||
import javax.annotation.Nullable;
|
||||
import java.util.Collection;
|
||||
|
||||
/**
|
||||
*
|
||||
* @author sk89q
|
||||
* @param <T>
|
||||
* A flag carries extra data on a region.
|
||||
*/
|
||||
public abstract class Flag<T> {
|
||||
|
||||
private String name;
|
||||
private RegionGroupFlag regionGroup;
|
||||
|
||||
public Flag(String name, RegionGroup defaultGroup) {
|
||||
this.name = name;
|
||||
private final String name;
|
||||
private final RegionGroupFlag regionGroup;
|
||||
|
||||
if (defaultGroup != null) {
|
||||
this.regionGroup = new RegionGroupFlag(name + "-group", defaultGroup);
|
||||
}
|
||||
/**
|
||||
* Create a new flag.
|
||||
*
|
||||
* @param name The name of the flag
|
||||
* @param defaultGroup The default group
|
||||
*/
|
||||
public Flag(String name, @Nullable RegionGroup defaultGroup) {
|
||||
this.name = name;
|
||||
this.regionGroup = defaultGroup != null ? new RegionGroupFlag(name + "-group", defaultGroup) : null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a new flag with {@link RegionGroup#ALL} as the default group.
|
||||
*
|
||||
* @param name The name of the flag
|
||||
*/
|
||||
public Flag(String name) {
|
||||
this(name, RegionGroup.ALL);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the name of the flag.
|
||||
*
|
||||
* @return The name of the flag
|
||||
*/
|
||||
public String getName() {
|
||||
return name;
|
||||
}
|
||||
@@ -54,7 +66,7 @@ public abstract class Flag<T> {
|
||||
/**
|
||||
* Get the default value.
|
||||
*
|
||||
* @return the default value, if one exists, otherwise {@code null} may be returned
|
||||
* @return The default value, if one exists, otherwise {@code null} may be returned
|
||||
*/
|
||||
@Nullable
|
||||
public T getDefault() {
|
||||
@@ -69,15 +81,101 @@ public abstract class Flag<T> {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Whether the flag can take a list of values and choose a "best one."
|
||||
*
|
||||
* <p>This is the case with the {@link StateFlag} where {@code DENY}
|
||||
* overrides {@code ALLOW}, but most flags just return the
|
||||
* first result from a list.</p>
|
||||
*
|
||||
* <p>This flag is primarily used to optimize flag lookup in
|
||||
* {@link FlagValueCalculator}.</p>
|
||||
*
|
||||
* @return Whether a best value can be chosen
|
||||
*/
|
||||
public boolean hasConflictStrategy() {
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Whether the flag implicitly has a value set as long as
|
||||
* {@link DefaultFlag#PASSTHROUGH} is not set.
|
||||
*
|
||||
* <p>This value is only changed, at least in WorldGuard, for the
|
||||
* {@link DefaultFlag#BUILD} flag.</p>
|
||||
*
|
||||
* @return Whether the flag is ignored
|
||||
*/
|
||||
public boolean implicitlySetWithMembership() {
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Whether, if the flag is not set at all, the value should be derived
|
||||
* from membership.
|
||||
*
|
||||
* <p>This value is only changed, at least in WorldGuard, for the
|
||||
* {@link DefaultFlag#BUILD} flag.</p>
|
||||
*
|
||||
* @return Whether membership is used
|
||||
*/
|
||||
public boolean usesMembershipAsDefault() {
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Whether the flag requires that a subject is specified in
|
||||
* {@link FlagValueCalculator}.
|
||||
*
|
||||
* <p>This value is only changed, at least in WorldGuard, for the
|
||||
* {@link DefaultFlag#BUILD} flag.</p>
|
||||
*
|
||||
* @return Whether a subject is required
|
||||
*/
|
||||
public boolean requiresSubject() {
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the region group flag.
|
||||
*
|
||||
* <p>Every group has a region group flag except for region group flags
|
||||
* themselves.</p>
|
||||
*
|
||||
* @return The region group flag
|
||||
*/
|
||||
public RegionGroupFlag getRegionGroupFlag() {
|
||||
return regionGroup;
|
||||
}
|
||||
|
||||
/**
|
||||
* Parse a given input to coerce it to a type compatible with the flag.
|
||||
*
|
||||
* @param plugin The plugin
|
||||
* @param sender The sender
|
||||
* @param input THe input
|
||||
* @return The coerced type
|
||||
* @throws InvalidFlagFormat Raised if the input is invalid
|
||||
*/
|
||||
public abstract T parseInput(WorldGuardPlugin plugin, CommandSender sender, String input) throws InvalidFlagFormat;
|
||||
|
||||
/**
|
||||
* Convert a raw type that was loaded (from a YAML file, for example)
|
||||
* into the type that this flag uses.
|
||||
*
|
||||
* @param o The object
|
||||
* @return The unmarshalled type
|
||||
*/
|
||||
public abstract T unmarshal(@Nullable Object o);
|
||||
|
||||
/**
|
||||
* Convert the value stored for this flag into a type that can be
|
||||
* serialized into YAML.
|
||||
*
|
||||
* @param o The object
|
||||
* @return The marshalled type
|
||||
*/
|
||||
public abstract Object marshal(T o);
|
||||
|
||||
@Override
|
||||
|
||||
@@ -24,8 +24,7 @@ import org.bukkit.command.CommandSender;
|
||||
import com.sk89q.worldguard.bukkit.WorldGuardPlugin;
|
||||
|
||||
/**
|
||||
*
|
||||
* @author sk89q
|
||||
* Stores an integer.
|
||||
*/
|
||||
public class IntegerFlag extends Flag<Integer> {
|
||||
|
||||
@@ -38,8 +37,7 @@ public class IntegerFlag extends Flag<Integer> {
|
||||
}
|
||||
|
||||
@Override
|
||||
public Integer parseInput(WorldGuardPlugin plugin, CommandSender sender,
|
||||
String input) throws InvalidFlagFormat {
|
||||
public Integer parseInput(WorldGuardPlugin plugin, CommandSender sender,String input) throws InvalidFlagFormat {
|
||||
input = input.trim();
|
||||
|
||||
try {
|
||||
|
||||
@@ -27,6 +27,9 @@ import org.bukkit.Bukkit;
|
||||
|
||||
import javax.annotation.Nullable;
|
||||
|
||||
/**
|
||||
* A location that stores the name of the world in case the world is unloaded.
|
||||
*/
|
||||
class LazyLocation extends Location {
|
||||
|
||||
private final String worldName;
|
||||
@@ -66,6 +69,4 @@ class LazyLocation extends Location {
|
||||
return this.setPosition(getPosition().add(x, y, z));
|
||||
}
|
||||
|
||||
|
||||
|
||||
}
|
||||
@@ -26,8 +26,7 @@ import com.sk89q.worldguard.protection.regions.ProtectedRegion;
|
||||
import javax.annotation.Nullable;
|
||||
|
||||
/**
|
||||
*
|
||||
* @author sk89q
|
||||
* Stores a region group.
|
||||
*/
|
||||
public class RegionGroupFlag extends EnumFlag<RegionGroup> {
|
||||
|
||||
|
||||
@@ -19,6 +19,7 @@
|
||||
|
||||
package com.sk89q.worldguard.protection.flags;
|
||||
|
||||
import com.google.common.collect.Sets;
|
||||
import com.sk89q.worldguard.bukkit.WorldGuardPlugin;
|
||||
import org.bukkit.command.CommandSender;
|
||||
|
||||
@@ -29,9 +30,7 @@ import java.util.List;
|
||||
import java.util.Set;
|
||||
|
||||
/**
|
||||
* Represents a flag that consists of a set.
|
||||
*
|
||||
* @author sk89q
|
||||
* Stores a set of types.
|
||||
*/
|
||||
public class SetFlag<T> extends Flag<Set<T>> {
|
||||
|
||||
@@ -57,15 +56,18 @@ public class SetFlag<T> extends Flag<Set<T>> {
|
||||
}
|
||||
|
||||
@Override
|
||||
public Set<T> parseInput(WorldGuardPlugin plugin, CommandSender sender,
|
||||
String input) throws InvalidFlagFormat {
|
||||
Set<T> items = new HashSet<T>();
|
||||
public Set<T> parseInput(WorldGuardPlugin plugin, CommandSender sender, String input) throws InvalidFlagFormat {
|
||||
if (input.isEmpty()) {
|
||||
return Sets.newHashSet();
|
||||
} else {
|
||||
Set<T> items = Sets.newHashSet();
|
||||
|
||||
for (String str : input.split(",")) {
|
||||
items.add(subFlag.parseInput(plugin, sender, str.trim()));
|
||||
for (String str : input.split(",")) {
|
||||
items.add(subFlag.parseInput(plugin, sender, str.trim()));
|
||||
}
|
||||
|
||||
return items;
|
||||
}
|
||||
|
||||
return new HashSet<T>(items);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
@@ -26,8 +26,7 @@ import javax.annotation.Nullable;
|
||||
import java.util.Collection;
|
||||
|
||||
/**
|
||||
*
|
||||
* @author sk89q
|
||||
* Stores a bi-state value.
|
||||
*/
|
||||
public class StateFlag extends Flag<StateFlag.State> {
|
||||
|
||||
@@ -53,6 +52,11 @@ public class StateFlag extends Flag<StateFlag.State> {
|
||||
return def ? State.ALLOW : null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean hasConflictStrategy() {
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
@Nullable
|
||||
public State chooseValue(Collection<State> values) {
|
||||
@@ -63,9 +67,21 @@ public class StateFlag extends Flag<StateFlag.State> {
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Whether setting this flag to {@link State#ALLOW} is prevented on
|
||||
* the global region.
|
||||
*
|
||||
* <p>This value is only changed, at least in WorldGuard, for the
|
||||
* {@link DefaultFlag#BUILD} flag.</p>
|
||||
*
|
||||
* @return Whether {@code ALLOW} is prevented
|
||||
*/
|
||||
public boolean preventsAllowOnGlobal() {
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public State parseInput(WorldGuardPlugin plugin, CommandSender sender,
|
||||
String input) throws InvalidFlagFormat {
|
||||
public State parseInput(WorldGuardPlugin plugin, CommandSender sender, String input) throws InvalidFlagFormat {
|
||||
input = input.trim();
|
||||
|
||||
if (input.equalsIgnoreCase("allow")) {
|
||||
|
||||
@@ -26,8 +26,7 @@ import com.sk89q.worldguard.bukkit.WorldGuardPlugin;
|
||||
import javax.annotation.Nullable;
|
||||
|
||||
/**
|
||||
*
|
||||
* @author sk89q
|
||||
* Stores a string.
|
||||
*/
|
||||
public class StringFlag extends Flag<String> {
|
||||
|
||||
@@ -60,8 +59,7 @@ public class StringFlag extends Flag<String> {
|
||||
}
|
||||
|
||||
@Override
|
||||
public String parseInput(WorldGuardPlugin plugin, CommandSender sender,
|
||||
String input) throws InvalidFlagFormat {
|
||||
public String parseInput(WorldGuardPlugin plugin, CommandSender sender, String input) throws InvalidFlagFormat {
|
||||
return input.replaceAll("(?!\\\\)\\\\n", "\n").replaceAll("\\\\\\\\n", "\\n");
|
||||
}
|
||||
|
||||
|
||||
@@ -19,19 +19,17 @@
|
||||
|
||||
package com.sk89q.worldguard.protection.flags;
|
||||
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
|
||||
import org.bukkit.command.CommandSender;
|
||||
|
||||
import com.sk89q.minecraft.util.commands.CommandException;
|
||||
import com.sk89q.worldedit.Vector;
|
||||
import com.sk89q.worldguard.bukkit.BukkitUtil;
|
||||
import com.sk89q.worldguard.bukkit.WorldGuardPlugin;
|
||||
import org.bukkit.command.CommandSender;
|
||||
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
|
||||
/**
|
||||
*
|
||||
* @author sk89q
|
||||
* Stores a vector.
|
||||
*/
|
||||
public class VectorFlag extends Flag<Vector> {
|
||||
|
||||
|
||||
@@ -21,6 +21,7 @@ package com.sk89q.worldguard.protection.managers;
|
||||
|
||||
import com.google.common.base.Predicate;
|
||||
import com.google.common.base.Supplier;
|
||||
import com.google.common.collect.Sets;
|
||||
import com.sk89q.worldedit.Vector;
|
||||
import com.sk89q.worldedit.Vector2D;
|
||||
import com.sk89q.worldguard.LocalPlayer;
|
||||
@@ -317,7 +318,7 @@ public final class RegionManager {
|
||||
public ApplicableRegionSet getApplicableRegions(Vector position) {
|
||||
checkNotNull(position);
|
||||
|
||||
List<ProtectedRegion> regions = new ArrayList<ProtectedRegion>();
|
||||
Set<ProtectedRegion> regions = Sets.newHashSet();
|
||||
index.applyContaining(position, new RegionCollectionConsumer(regions, true));
|
||||
return new RegionResultSet(regions, index.get("__global__"));
|
||||
}
|
||||
@@ -332,7 +333,7 @@ public final class RegionManager {
|
||||
public ApplicableRegionSet getApplicableRegions(ProtectedRegion region) {
|
||||
checkNotNull(region);
|
||||
|
||||
List<ProtectedRegion> regions = new ArrayList<ProtectedRegion>();
|
||||
Set<ProtectedRegion> regions = Sets.newHashSet();
|
||||
index.applyIntersecting(region, new RegionCollectionConsumer(regions, true));
|
||||
return new RegionResultSet(regions, index.get("__global__"));
|
||||
}
|
||||
@@ -441,7 +442,7 @@ public final class RegionManager {
|
||||
* @return an {@code ApplicableRegionSet}
|
||||
*/
|
||||
public ApplicableRegionSet getApplicableRegions(org.bukkit.Location loc) {
|
||||
return getApplicableRegions(com.sk89q.worldedit.bukkit.BukkitUtil.toVector(loc));
|
||||
return getApplicableRegions(com.sk89q.worldedit.bukkit.BukkitUtil.toVector(loc).floor());
|
||||
}
|
||||
|
||||
}
|
||||
@@ -23,8 +23,10 @@ import com.sk89q.worldedit.BlockVector;
|
||||
import com.sk89q.worldedit.BlockVector2D;
|
||||
import com.sk89q.worldedit.Vector;
|
||||
|
||||
import java.awt.geom.Area;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collection;
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
@@ -47,6 +49,11 @@ public class GlobalProtectedRegion extends ProtectedRegion {
|
||||
max = new BlockVector(0, 0, 0);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isPhysicalArea() {
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<BlockVector2D> getPoints() {
|
||||
// This doesn't make sense
|
||||
@@ -74,7 +81,12 @@ public class GlobalProtectedRegion extends ProtectedRegion {
|
||||
@Override
|
||||
public List<ProtectedRegion> getIntersectingRegions(Collection<ProtectedRegion> regions) {
|
||||
// Global regions are handled separately so it must not contain any positions
|
||||
return new ArrayList<ProtectedRegion>();
|
||||
return Collections.emptyList();
|
||||
}
|
||||
|
||||
@Override
|
||||
Area toArea() {
|
||||
return null;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -24,8 +24,9 @@ import com.sk89q.worldedit.BlockVector2D;
|
||||
import com.sk89q.worldedit.Vector;
|
||||
import com.sk89q.worldguard.util.MathUtils;
|
||||
|
||||
import java.awt.*;
|
||||
import java.awt.geom.Area;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collection;
|
||||
import java.util.List;
|
||||
|
||||
import static com.google.common.base.Preconditions.checkNotNull;
|
||||
@@ -83,6 +84,11 @@ public class ProtectedCuboidRegion extends ProtectedRegion {
|
||||
setMinMaxPoints(min, position);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isPhysicalArea() {
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<BlockVector2D> getPoints() {
|
||||
List<BlockVector2D> pts = new ArrayList<BlockVector2D>();
|
||||
@@ -115,30 +121,21 @@ public class ProtectedCuboidRegion extends ProtectedRegion {
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<ProtectedRegion> getIntersectingRegions(Collection<ProtectedRegion> regions) {
|
||||
checkNotNull(regions);
|
||||
Area toArea() {
|
||||
int x = getMinimumPoint().getBlockX();
|
||||
int z = getMinimumPoint().getBlockZ();
|
||||
int width = getMaximumPoint().getBlockX() - x;
|
||||
int height = getMaximumPoint().getBlockZ() - z;
|
||||
return new Area(new Rectangle(x, z, width, height));
|
||||
}
|
||||
|
||||
List<ProtectedRegion> intersectingRegions = new ArrayList<ProtectedRegion>();
|
||||
|
||||
for (ProtectedRegion region : regions) {
|
||||
if (!intersectsBoundingBox(region)) continue;
|
||||
|
||||
// If both regions are Cuboids and their bounding boxes intersect, they intersect
|
||||
if (region instanceof ProtectedCuboidRegion) {
|
||||
intersectingRegions.add(region);
|
||||
} else if (region instanceof ProtectedPolygonalRegion) {
|
||||
// If either region contains the points of the other,
|
||||
// or if any edges intersect, the regions intersect
|
||||
if (containsAny(region.getPoints()) || region.containsAny(getPoints()) || intersectsEdges(region)) {
|
||||
intersectingRegions.add(region);
|
||||
}
|
||||
} else if (region instanceof GlobalProtectedRegion) {
|
||||
// Never intersects
|
||||
} else {
|
||||
throw new IllegalArgumentException("Not supported yet.");
|
||||
}
|
||||
@Override
|
||||
protected boolean intersects(ProtectedRegion region, Area thisArea) {
|
||||
if (region instanceof ProtectedCuboidRegion) {
|
||||
return intersectsBoundingBox(region);
|
||||
} else {
|
||||
return super.intersects(region, thisArea);
|
||||
}
|
||||
return intersectingRegions;
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
+27
-25
@@ -19,25 +19,28 @@
|
||||
|
||||
package com.sk89q.worldguard.protection.regions;
|
||||
|
||||
import com.google.common.collect.ImmutableList;
|
||||
import com.sk89q.worldedit.BlockVector2D;
|
||||
import com.sk89q.worldedit.Vector;
|
||||
|
||||
import java.awt.*;
|
||||
import java.awt.geom.Area;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collection;
|
||||
import java.util.List;
|
||||
|
||||
import static com.google.common.base.Preconditions.checkNotNull;
|
||||
|
||||
public class ProtectedPolygonalRegion extends ProtectedRegion {
|
||||
|
||||
private List<BlockVector2D> points;
|
||||
private int minY;
|
||||
private int maxY;
|
||||
private final ImmutableList<BlockVector2D> points;
|
||||
private final int minY;
|
||||
private final int maxY;
|
||||
|
||||
public ProtectedPolygonalRegion(String id, List<BlockVector2D> points, int minY, int maxY) {
|
||||
super(id);
|
||||
setMinMaxPoints(points, minY, maxY);
|
||||
this.points = points;
|
||||
ImmutableList<BlockVector2D> immutablePoints = ImmutableList.copyOf(points);
|
||||
setMinMaxPoints(immutablePoints, minY, maxY);
|
||||
this.points = immutablePoints;
|
||||
this.minY = min.getBlockY();
|
||||
this.maxY = max.getBlockY();
|
||||
}
|
||||
@@ -61,6 +64,11 @@ public class ProtectedPolygonalRegion extends ProtectedRegion {
|
||||
setMinMaxPoints(points);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isPhysicalArea() {
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<BlockVector2D> getPoints() {
|
||||
return points;
|
||||
@@ -133,27 +141,21 @@ public class ProtectedPolygonalRegion extends ProtectedRegion {
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<ProtectedRegion> getIntersectingRegions(Collection<ProtectedRegion> regions) {
|
||||
checkNotNull(regions);
|
||||
Area toArea() {
|
||||
List<BlockVector2D> points = getPoints();
|
||||
int numPoints = points.size();
|
||||
int[] xCoords = new int[numPoints];
|
||||
int[] yCoords = new int[numPoints];
|
||||
|
||||
List<ProtectedRegion> intersectingRegions = new ArrayList<ProtectedRegion>();
|
||||
|
||||
for (ProtectedRegion region : regions) {
|
||||
if (!intersectsBoundingBox(region)) continue;
|
||||
|
||||
if (region instanceof ProtectedPolygonalRegion || region instanceof ProtectedCuboidRegion) {
|
||||
// If either region contains the points of the other,
|
||||
// or if any edges intersect, the regions intersect
|
||||
if (containsAny(region.getPoints()) || region.containsAny(getPoints()) || intersectsEdges(region)) {
|
||||
intersectingRegions.add(region);
|
||||
}
|
||||
} else if (region instanceof GlobalProtectedRegion) {
|
||||
// Never intersects
|
||||
} else {
|
||||
throw new IllegalArgumentException("Not supported yet.");
|
||||
}
|
||||
int i = 0;
|
||||
for (BlockVector2D point : points) {
|
||||
xCoords[i] = point.getBlockX();
|
||||
yCoords[i] = point.getBlockZ();
|
||||
i++;
|
||||
}
|
||||
return intersectingRegions;
|
||||
|
||||
Polygon polygon = new Polygon(xCoords, yCoords, numPoints);
|
||||
return new Area(polygon);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
@@ -19,6 +19,7 @@
|
||||
|
||||
package com.sk89q.worldguard.protection.regions;
|
||||
|
||||
import com.google.common.collect.Lists;
|
||||
import com.sk89q.worldedit.BlockVector;
|
||||
import com.sk89q.worldedit.BlockVector2D;
|
||||
import com.sk89q.worldedit.Vector;
|
||||
@@ -29,6 +30,7 @@ import com.sk89q.worldguard.util.ChangeTracked;
|
||||
import com.sk89q.worldguard.util.Normal;
|
||||
|
||||
import javax.annotation.Nullable;
|
||||
import java.awt.geom.Area;
|
||||
import java.awt.geom.Line2D;
|
||||
import java.util.Collection;
|
||||
import java.util.List;
|
||||
@@ -118,6 +120,13 @@ public abstract class ProtectedRegion implements ChangeTracked, Comparable<Prote
|
||||
return id;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return whether this type of region encompasses physical area.
|
||||
*
|
||||
* @return Whether physical area is encompassed
|
||||
*/
|
||||
public abstract boolean isPhysicalArea();
|
||||
|
||||
/**
|
||||
* Get a vector containing the smallest X, Y, and Z components for the
|
||||
* corner of the axis-aligned bounding box that contains this region.
|
||||
@@ -224,7 +233,7 @@ public abstract class ProtectedRegion implements ChangeTracked, Comparable<Prote
|
||||
public void setOwners(DefaultDomain owners) {
|
||||
checkNotNull(owners);
|
||||
setDirty(true);
|
||||
this.owners = owners;
|
||||
this.owners = new DefaultDomain(owners);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -245,7 +254,7 @@ public abstract class ProtectedRegion implements ChangeTracked, Comparable<Prote
|
||||
public void setMembers(DefaultDomain members) {
|
||||
checkNotNull(members);
|
||||
setDirty(true);
|
||||
this.members = members;
|
||||
this.members = new DefaultDomain(members);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -570,7 +579,39 @@ public abstract class ProtectedRegion implements ChangeTracked, Comparable<Prote
|
||||
* @param regions a list of regions to source from
|
||||
* @return the elements of {@code regions} that intersect with this region
|
||||
*/
|
||||
public abstract List<ProtectedRegion> getIntersectingRegions(Collection<ProtectedRegion> regions);
|
||||
public List<ProtectedRegion> getIntersectingRegions(Collection<ProtectedRegion> regions) {
|
||||
checkNotNull(regions, "regions");
|
||||
|
||||
List<ProtectedRegion> intersecting = Lists.newArrayList();
|
||||
Area thisArea = toArea();
|
||||
|
||||
for (ProtectedRegion region : regions) {
|
||||
if (!region.isPhysicalArea()) continue;
|
||||
|
||||
if (intersects(region, thisArea)) {
|
||||
intersecting.add(region);
|
||||
}
|
||||
}
|
||||
|
||||
return intersecting;
|
||||
}
|
||||
|
||||
/**
|
||||
* Test whether the given region intersects with this area.
|
||||
*
|
||||
* @param region the region to test
|
||||
* @param thisArea an area object for this region
|
||||
* @return true if the two regions intersect
|
||||
*/
|
||||
protected boolean intersects(ProtectedRegion region, Area thisArea) {
|
||||
if (intersectsBoundingBox(region)) {
|
||||
Area testArea = region.toArea();
|
||||
testArea.intersect(thisArea);
|
||||
return !testArea.isEmpty();
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks if the bounding box of a region intersects with with the bounding
|
||||
@@ -631,6 +672,14 @@ public abstract class ProtectedRegion implements ChangeTracked, Comparable<Prote
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the AWT area, otherwise null if
|
||||
* {@link #isPhysicalArea()} if false.
|
||||
*
|
||||
* @return The shape version
|
||||
*/
|
||||
abstract Area toArea();
|
||||
|
||||
@Override
|
||||
public boolean isDirty() {
|
||||
return dirty || owners.isDirty() || members.isDirty();
|
||||
|
||||
@@ -0,0 +1,144 @@
|
||||
/*
|
||||
* WorldGuard, a suite of tools for Minecraft
|
||||
* Copyright (C) sk89q <http://www.sk89q.com>
|
||||
* Copyright (C) WorldGuard team and contributors
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify it
|
||||
* under the terms of the GNU Lesser General Public License as published by the
|
||||
* Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License
|
||||
* for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
package com.sk89q.worldguard.protection.util;
|
||||
|
||||
import com.google.common.collect.Lists;
|
||||
import com.google.common.collect.Maps;
|
||||
import com.google.common.collect.Sets;
|
||||
import com.sk89q.worldguard.protection.ApplicableRegionSet;
|
||||
import com.sk89q.worldguard.protection.FlagValueCalculator;
|
||||
import com.sk89q.worldguard.protection.regions.ProtectedRegion;
|
||||
|
||||
import javax.annotation.Nullable;
|
||||
import java.util.*;
|
||||
|
||||
/**
|
||||
* Sorts a list of regions so that higher priority regions always take
|
||||
* precedence over lower priority ones, and after sorting by priority, so
|
||||
* child regions always take priority over their parent regions.
|
||||
*
|
||||
* <p>For example, if the regions are a, aa, aaa, aab, aac, b, ba, bc, where
|
||||
* aa implies that the second 'a' is a child of the first 'a', the sorted
|
||||
* order must reflect the following properties (where regions on the
|
||||
* left of < appear before in the sorted list):</p>
|
||||
*
|
||||
* <ul>
|
||||
* <li>[aaa, aab, aac] < aa < a</li>
|
||||
* <li>[ba, bc] < b</li>
|
||||
* </ul>
|
||||
*
|
||||
* <p>In the case of "[aaa, aab, aac]," the relative order between these
|
||||
* regions is unimportant as they all share the same parent (aaa). The
|
||||
* following choices would be valid sorts:</p>
|
||||
*
|
||||
* <ul>
|
||||
* <li>aaa, aab, aac, aa, a, ba, bc, b</li>
|
||||
* <li>aab, aaa, aac, aa, a, bc, ba, b</li>
|
||||
* <li>bc, ba, b, aab, aaa, aac, aa, a</li>
|
||||
* <li>aab, aaa, bc, aac, aa, ba, a, b</li>
|
||||
* </ul>
|
||||
*
|
||||
* <p>These sorted lists are required for {@link FlagValueCalculator} and
|
||||
* some implementations of {@link ApplicableRegionSet}.</p>
|
||||
*/
|
||||
public final class NormativeOrders {
|
||||
|
||||
private static final PriorityComparator PRIORITY_COMPARATOR = new PriorityComparator();
|
||||
|
||||
private NormativeOrders() {
|
||||
}
|
||||
|
||||
public static void sort(List<ProtectedRegion> regions) {
|
||||
sortInto(Sets.newHashSet(regions), regions);
|
||||
}
|
||||
|
||||
public static List<ProtectedRegion> fromSet(Set<ProtectedRegion> regions) {
|
||||
List<ProtectedRegion> sorted = Arrays.asList(new ProtectedRegion[regions.size()]);
|
||||
sortInto(regions, sorted);
|
||||
return sorted;
|
||||
}
|
||||
|
||||
private static void sortInto(Set<ProtectedRegion> regions, List<ProtectedRegion> sorted) {
|
||||
List<RegionNode> root = Lists.newArrayList();
|
||||
Map<ProtectedRegion, RegionNode> nodes = Maps.newHashMap();
|
||||
for (ProtectedRegion region : regions) {
|
||||
addNode(nodes, root, region);
|
||||
}
|
||||
|
||||
int index = regions.size() - 1;
|
||||
for (RegionNode node : root) {
|
||||
while (node != null) {
|
||||
if (regions.contains(node.region)) {
|
||||
sorted.set(index, node.region);
|
||||
index--;
|
||||
}
|
||||
node = node.next;
|
||||
}
|
||||
}
|
||||
|
||||
Collections.sort(sorted, PRIORITY_COMPARATOR);
|
||||
}
|
||||
|
||||
private static RegionNode addNode(Map<ProtectedRegion, RegionNode> nodes, List<RegionNode> root, ProtectedRegion region) {
|
||||
RegionNode node = nodes.get(region);
|
||||
if (node == null) {
|
||||
node = new RegionNode(region);
|
||||
nodes.put(region, node);
|
||||
if (region.getParent() != null) {
|
||||
addNode(nodes, root, region.getParent()).insertAfter(node);
|
||||
} else {
|
||||
root.add(node);
|
||||
}
|
||||
}
|
||||
return node;
|
||||
}
|
||||
|
||||
private static class RegionNode {
|
||||
@Nullable private RegionNode next;
|
||||
private final ProtectedRegion region;
|
||||
|
||||
private RegionNode(ProtectedRegion region) {
|
||||
this.region = region;
|
||||
}
|
||||
|
||||
private void insertAfter(RegionNode node) {
|
||||
if (this.next == null) {
|
||||
this.next = node;
|
||||
} else {
|
||||
node.next = this.next;
|
||||
this.next = node;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private static class PriorityComparator implements Comparator<ProtectedRegion> {
|
||||
@Override
|
||||
public int compare(ProtectedRegion o1, ProtectedRegion o2) {
|
||||
if (o1.getPriority() > o2.getPriority()) {
|
||||
return -1;
|
||||
} else if (o1.getPriority() < o2.getPriority()) {
|
||||
return 1;
|
||||
} else {
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,54 @@
|
||||
/*
|
||||
* WorldGuard, a suite of tools for Minecraft
|
||||
* Copyright (C) sk89q <http://www.sk89q.com>
|
||||
* Copyright (C) WorldGuard team and contributors
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify it
|
||||
* under the terms of the GNU Lesser General Public License as published by the
|
||||
* Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License
|
||||
* for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
package com.sk89q.worldguard.session;
|
||||
|
||||
import org.bukkit.Location;
|
||||
|
||||
/**
|
||||
* Types of movements.
|
||||
*
|
||||
* <p>Used with {@link Session#testMoveTo(Location, MoveType)}.</p>
|
||||
*/
|
||||
public enum MoveType {
|
||||
|
||||
RESPAWN(false, true),
|
||||
EMBARK(true, false),
|
||||
MOVE(true, false),
|
||||
TELEPORT(true, true),
|
||||
RIDE(true, false),
|
||||
OTHER_NON_CANCELLABLE(false, false),
|
||||
OTHER_CANCELLABLE(true, false);
|
||||
|
||||
private final boolean cancellable;
|
||||
private final boolean teleport;
|
||||
|
||||
MoveType(boolean cancellable, boolean teleport) {
|
||||
this.cancellable = cancellable;
|
||||
this.teleport = teleport;
|
||||
}
|
||||
|
||||
public boolean isCancellable() {
|
||||
return cancellable;
|
||||
}
|
||||
|
||||
public boolean isTeleport() {
|
||||
return teleport;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,229 @@
|
||||
/*
|
||||
* 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.session;
|
||||
|
||||
import com.google.common.collect.Maps;
|
||||
import com.google.common.collect.Sets;
|
||||
import com.sk89q.worldguard.bukkit.RegionQuery;
|
||||
import com.sk89q.worldguard.bukkit.WorldGuardPlugin;
|
||||
import com.sk89q.worldguard.bukkit.util.Locations;
|
||||
import com.sk89q.worldguard.protection.ApplicableRegionSet;
|
||||
import com.sk89q.worldguard.protection.flags.StateFlag.State;
|
||||
import com.sk89q.worldguard.protection.regions.ProtectedRegion;
|
||||
import com.sk89q.worldguard.session.handler.Handler;
|
||||
import org.bukkit.Location;
|
||||
import org.bukkit.entity.Player;
|
||||
|
||||
import javax.annotation.Nullable;
|
||||
import java.util.HashMap;
|
||||
import java.util.Set;
|
||||
import java.util.concurrent.atomic.AtomicBoolean;
|
||||
|
||||
import static com.google.common.base.Preconditions.checkNotNull;
|
||||
|
||||
/**
|
||||
* Keeps session information on a player.
|
||||
*/
|
||||
public class Session {
|
||||
|
||||
private final SessionManager manager;
|
||||
private final HashMap<Class<?>, Handler> handlers = Maps.newLinkedHashMap();
|
||||
private Location lastValid;
|
||||
private Set<ProtectedRegion> lastRegionSet;
|
||||
private final AtomicBoolean needRefresh = new AtomicBoolean(false);
|
||||
|
||||
/**
|
||||
* Create a new session.
|
||||
*
|
||||
* @param manager The session manager
|
||||
*/
|
||||
public Session(SessionManager manager) {
|
||||
checkNotNull(manager, "manager");
|
||||
this.manager = manager;
|
||||
}
|
||||
|
||||
/**
|
||||
* Register a new handler.
|
||||
*
|
||||
* @param handler A new handler
|
||||
*/
|
||||
void register(Handler handler) {
|
||||
handlers.put(handler.getClass(), handler);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the plugin.
|
||||
*
|
||||
* @return The plugin
|
||||
*/
|
||||
public WorldGuardPlugin getPlugin() {
|
||||
return getManager().getPlugin();
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the session manager.
|
||||
*
|
||||
* @return The session manager
|
||||
*/
|
||||
public SessionManager getManager() {
|
||||
return manager;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get a handler by class, if has been registered.
|
||||
*
|
||||
* @param type The type of handler
|
||||
* @param <T> The type of handler
|
||||
* @return A handler instance, otherwise null
|
||||
*/
|
||||
@Nullable
|
||||
@SuppressWarnings("unchecked")
|
||||
public <T extends Handler> T getHandler(Class<T> type) {
|
||||
return (T) handlers.get(type);
|
||||
}
|
||||
|
||||
/**
|
||||
* Initialize the session.
|
||||
*
|
||||
* @param player The player
|
||||
*/
|
||||
void initialize(Player player) {
|
||||
RegionQuery query = getManager().getPlugin().getRegionContainer().createQuery();
|
||||
Location location = player.getLocation();
|
||||
ApplicableRegionSet set = query.getApplicableRegions(location);
|
||||
|
||||
lastValid = location;
|
||||
lastRegionSet = set.getRegions();
|
||||
|
||||
for (Handler handler : handlers.values()) {
|
||||
handler.initialize(player, location, set);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Tick the session.
|
||||
*
|
||||
* @param player The player
|
||||
*/
|
||||
void tick(Player player) {
|
||||
RegionQuery query = getManager().getPlugin().getRegionContainer().createQuery();
|
||||
Location location = player.getLocation();
|
||||
ApplicableRegionSet set = query.getApplicableRegions(location);
|
||||
|
||||
for (Handler handler : handlers.values()) {
|
||||
handler.tick(player, set);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Re-initialize the session.
|
||||
*
|
||||
* @param player The player
|
||||
*/
|
||||
void resetState(Player player) {
|
||||
initialize(player);
|
||||
needRefresh.set(true);
|
||||
}
|
||||
|
||||
/**
|
||||
* Test whether the session has invincibility enabled.
|
||||
*
|
||||
* @return Whether invincibility is enabled
|
||||
*/
|
||||
public boolean isInvincible(Player player) {
|
||||
boolean invincible = false;
|
||||
|
||||
for (Handler handler : handlers.values()) {
|
||||
State state = handler.getInvincibility(player);
|
||||
if (state != null) {
|
||||
switch (state) {
|
||||
case DENY: return false;
|
||||
case ALLOW: invincible = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return invincible;
|
||||
}
|
||||
|
||||
/**
|
||||
* Test movement to the given location.
|
||||
*
|
||||
* @param player The player
|
||||
* @param to The new location
|
||||
* @param moveType The type of move
|
||||
* @return The overridden location, if the location is being overridden
|
||||
* @see #testMoveTo(Player, Location, MoveType, boolean) For an explanation
|
||||
*/
|
||||
@Nullable
|
||||
public Location testMoveTo(Player player, Location to, MoveType moveType) {
|
||||
return testMoveTo(player, to, moveType, false);
|
||||
}
|
||||
|
||||
/**
|
||||
* Test movement to the given location.
|
||||
*
|
||||
* <p>If a non-null {@link Location} is returned, the player should be
|
||||
* at that location instead of where the player has tried to move to.</p>
|
||||
*
|
||||
* <p>If the {@code moveType} is cancellable
|
||||
* ({@link MoveType#isCancellable()}, then the last valid location will
|
||||
* be set to the given one.</p>
|
||||
*
|
||||
* @param player The player
|
||||
* @param to The new location
|
||||
* @param moveType The type of move
|
||||
* @param forced Whether to force a check
|
||||
* @return The overridden location, if the location is being overridden
|
||||
*/
|
||||
@Nullable
|
||||
public Location testMoveTo(Player player, Location to, MoveType moveType, boolean forced) {
|
||||
RegionQuery query = getManager().getPlugin().getRegionContainer().createQuery();
|
||||
|
||||
if (!forced && needRefresh.getAndSet(false)) {
|
||||
forced = true;
|
||||
}
|
||||
|
||||
if (forced || Locations.isDifferentBlock(lastValid, to)) {
|
||||
ApplicableRegionSet toSet = query.getApplicableRegions(to);
|
||||
|
||||
for (Handler handler : handlers.values()) {
|
||||
if (!handler.testMoveTo(player, lastValid, to, toSet, moveType) && moveType.isCancellable()) {
|
||||
return lastValid;
|
||||
}
|
||||
}
|
||||
|
||||
Set<ProtectedRegion> entered = Sets.difference(toSet.getRegions(), lastRegionSet);
|
||||
Set<ProtectedRegion> exited = Sets.difference(lastRegionSet, toSet.getRegions());
|
||||
|
||||
for (Handler handler : handlers.values()) {
|
||||
if (!handler.onCrossBoundary(player, lastValid, to, toSet, entered, exited, moveType) && moveType.isCancellable()) {
|
||||
return lastValid;
|
||||
}
|
||||
}
|
||||
|
||||
lastValid = to;
|
||||
lastRegionSet = toSet.getRegions();
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,221 @@
|
||||
/*
|
||||
* 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.session;
|
||||
|
||||
import com.sk89q.guavabackport.cache.CacheBuilder;
|
||||
import com.sk89q.guavabackport.cache.CacheLoader;
|
||||
import com.sk89q.guavabackport.cache.LoadingCache;
|
||||
import com.sk89q.worldguard.bukkit.BukkitUtil;
|
||||
import com.sk89q.worldguard.bukkit.WorldGuardPlugin;
|
||||
import com.sk89q.worldguard.session.handler.*;
|
||||
import org.bukkit.World;
|
||||
import org.bukkit.entity.Player;
|
||||
import org.bukkit.event.EventHandler;
|
||||
import org.bukkit.event.Listener;
|
||||
import org.bukkit.event.player.PlayerJoinEvent;
|
||||
|
||||
import javax.annotation.Nullable;
|
||||
import java.lang.ref.WeakReference;
|
||||
import java.util.Collection;
|
||||
import java.util.UUID;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
|
||||
import static com.google.common.base.Preconditions.checkNotNull;
|
||||
|
||||
/**
|
||||
* Keeps tracks of sessions and also does session-related handling
|
||||
* (flags, etc.).
|
||||
*/
|
||||
public class SessionManager implements Runnable, Listener {
|
||||
|
||||
public static final int RUN_DELAY = 20;
|
||||
public static final long SESSION_LIFETIME = 10;
|
||||
|
||||
private final WorldGuardPlugin plugin;
|
||||
|
||||
private final LoadingCache<WorldPlayerTuple, Boolean> bypassCache = CacheBuilder.newBuilder()
|
||||
.maximumSize(1000)
|
||||
.expireAfterAccess(2, TimeUnit.SECONDS)
|
||||
.build(new CacheLoader<WorldPlayerTuple, Boolean>() {
|
||||
@Override
|
||||
public Boolean load(WorldPlayerTuple tuple) throws Exception {
|
||||
return plugin.getGlobalRegionManager().hasBypass(tuple.player, tuple.world);
|
||||
}
|
||||
});
|
||||
|
||||
private final LoadingCache<CacheKey, Session> sessions = CacheBuilder.newBuilder()
|
||||
.expireAfterAccess(SESSION_LIFETIME, TimeUnit.MINUTES)
|
||||
.build(new CacheLoader<CacheKey, Session>() {
|
||||
@Override
|
||||
public Session load(CacheKey key) throws Exception {
|
||||
return createSession(key.playerRef.get());
|
||||
}
|
||||
});
|
||||
|
||||
/**
|
||||
* Create a new instance.
|
||||
*
|
||||
* @param plugin The plugin
|
||||
*/
|
||||
public SessionManager(WorldGuardPlugin plugin) {
|
||||
checkNotNull(plugin, "plugin");
|
||||
this.plugin = plugin;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the plugin.
|
||||
*
|
||||
* @return The plugin
|
||||
*/
|
||||
public WorldGuardPlugin getPlugin() {
|
||||
return plugin;
|
||||
}
|
||||
|
||||
/**
|
||||
* Check whether a player has the region bypass permission.
|
||||
*
|
||||
* <p>The return value may be cached for a few seconds.</p>
|
||||
*
|
||||
* @param player The player
|
||||
* @param world The world
|
||||
* @return A value
|
||||
*/
|
||||
public boolean hasBypass(Player player, World world) {
|
||||
return bypassCache.getUnchecked(new WorldPlayerTuple(world, player));
|
||||
}
|
||||
|
||||
/**
|
||||
* Re-initialize handlers and clear "last position," "last state," etc.
|
||||
* information for all players.
|
||||
*/
|
||||
public void resetAllStates() {
|
||||
Collection<? extends Player> players = BukkitUtil.getOnlinePlayers();
|
||||
for (Player player : players) {
|
||||
Session session = sessions.getIfPresent(new CacheKey(player));
|
||||
if (session != null) {
|
||||
session.resetState(player);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Re-initialize handlers and clear "last position," "last state," etc.
|
||||
* information.
|
||||
*
|
||||
* @param player The player
|
||||
*/
|
||||
public void resetState(Player player) {
|
||||
checkNotNull(player, "player");
|
||||
@Nullable Session session = sessions.getIfPresent(new CacheKey(player));
|
||||
if (session != null) {
|
||||
session.resetState(player);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a session for a player.
|
||||
*
|
||||
* @param player The player
|
||||
* @return The new session
|
||||
*/
|
||||
private Session createSession(Player player) {
|
||||
Session session = new Session(this);
|
||||
session.register(new HealFlag(session));
|
||||
session.register(new FeedFlag(session));
|
||||
session.register(new NotifyEntryFlag(session));
|
||||
session.register(new NotifyExitFlag(session));
|
||||
session.register(new EntryFlag(session));
|
||||
session.register(new ExitFlag(session));
|
||||
session.register(new GreetingFlag(session));
|
||||
session.register(new FarewellFlag(session));
|
||||
session.register(new GameModeFlag(session));
|
||||
session.register(new InvincibilityFlag(session));
|
||||
session.register(new TimeLockFlag(session));
|
||||
session.register(new WeatherLockFlag(session));
|
||||
session.register(new GodMode(session));
|
||||
session.register(new WaterBreathing(session));
|
||||
session.initialize(player);
|
||||
return session;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get a player's session, if one exists.
|
||||
*
|
||||
* @param player The player
|
||||
* @return The session
|
||||
*/
|
||||
@Nullable
|
||||
public Session getIfPresent(Player player) {
|
||||
return sessions.getIfPresent(player);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get a player's session. A session will be created if there is no
|
||||
* existing session for the player.
|
||||
*
|
||||
* <p>This method can only be called from the main thread. While the
|
||||
* session manager itself is thread-safe, some of the handlers may
|
||||
* require initialization that requires the server main thread.</p>
|
||||
*
|
||||
* @param player The player to get a session for
|
||||
* @return The {@code player}'s session
|
||||
*/
|
||||
public Session get(Player player) {
|
||||
return sessions.getUnchecked(new CacheKey(player));
|
||||
}
|
||||
|
||||
@EventHandler
|
||||
public void onPlayerJoin(PlayerJoinEvent event) {
|
||||
// Pre-load a session
|
||||
get(event.getPlayer());
|
||||
}
|
||||
|
||||
@Override
|
||||
public void run() {
|
||||
for (Player player : BukkitUtil.getOnlinePlayers()) {
|
||||
get(player).tick(player);
|
||||
}
|
||||
}
|
||||
|
||||
private static final class CacheKey {
|
||||
private final WeakReference<Player> playerRef;
|
||||
private final UUID uuid;
|
||||
|
||||
private CacheKey(Player player) {
|
||||
playerRef = new WeakReference<Player>(player);
|
||||
uuid = player.getUniqueId();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean equals(Object o) {
|
||||
if (this == o) return true;
|
||||
if (o == null || getClass() != o.getClass()) return false;
|
||||
CacheKey cacheKey = (CacheKey) o;
|
||||
return uuid.equals(cacheKey.uuid);
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public int hashCode() {
|
||||
return uuid.hashCode();
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,55 @@
|
||||
/*
|
||||
* 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.session;
|
||||
|
||||
import org.bukkit.World;
|
||||
import org.bukkit.entity.Player;
|
||||
|
||||
class WorldPlayerTuple {
|
||||
|
||||
final World world;
|
||||
final Player player;
|
||||
|
||||
WorldPlayerTuple(World world, Player player) {
|
||||
this.world = world;
|
||||
this.player = player;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean equals(Object o) {
|
||||
if (this == o) return true;
|
||||
if (o == null || getClass() != o.getClass()) return false;
|
||||
|
||||
WorldPlayerTuple that = (WorldPlayerTuple) o;
|
||||
|
||||
if (!player.equals(that.player)) return false;
|
||||
if (!world.equals(that.world)) return false;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int hashCode() {
|
||||
int result = world.hashCode();
|
||||
result = 31 * result + player.hashCode();
|
||||
return result;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,64 @@
|
||||
/*
|
||||
* WorldGuard, a suite of tools for Minecraft
|
||||
* Copyright (C) sk89q <http://www.sk89q.com>
|
||||
* Copyright (C) WorldGuard team and contributors
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify it
|
||||
* under the terms of the GNU Lesser General Public License as published by the
|
||||
* Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License
|
||||
* for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
package com.sk89q.worldguard.session.handler;
|
||||
|
||||
import com.sk89q.worldguard.LocalPlayer;
|
||||
import com.sk89q.worldguard.bukkit.commands.CommandUtils;
|
||||
import com.sk89q.worldguard.protection.ApplicableRegionSet;
|
||||
import com.sk89q.worldguard.protection.flags.DefaultFlag;
|
||||
import com.sk89q.worldguard.protection.regions.ProtectedRegion;
|
||||
import com.sk89q.worldguard.session.MoveType;
|
||||
import com.sk89q.worldguard.session.Session;
|
||||
import org.bukkit.Location;
|
||||
import org.bukkit.entity.Player;
|
||||
|
||||
import java.util.Set;
|
||||
|
||||
public class EntryFlag extends Handler {
|
||||
|
||||
private static final long MESSAGE_THRESHOLD = 1000 * 2;
|
||||
private long lastMessage;
|
||||
|
||||
public EntryFlag(Session session) {
|
||||
super(session);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean onCrossBoundary(Player player, Location from, Location to, ApplicableRegionSet toSet, Set<ProtectedRegion> entered, Set<ProtectedRegion> exited, MoveType moveType) {
|
||||
LocalPlayer localPlayer = getPlugin().wrapPlayer(player);
|
||||
boolean allowed = toSet.testState(localPlayer, DefaultFlag.ENTRY);
|
||||
|
||||
if (!getSession().getManager().hasBypass(player, to.getWorld()) && !allowed && moveType.isCancellable()) {
|
||||
String message = toSet.queryValue(localPlayer, DefaultFlag.ENTRY_DENY_MESSAGE);
|
||||
long now = System.currentTimeMillis();
|
||||
|
||||
if ((now - lastMessage) > MESSAGE_THRESHOLD && message != null && !message.isEmpty()) {
|
||||
player.sendMessage(CommandUtils.replaceColorMacros(message));
|
||||
lastMessage = now;
|
||||
}
|
||||
|
||||
return false;
|
||||
} else {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
@@ -0,0 +1,107 @@
|
||||
/*
|
||||
* 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.session.handler;
|
||||
|
||||
import com.sk89q.worldguard.LocalPlayer;
|
||||
import com.sk89q.worldguard.bukkit.commands.CommandUtils;
|
||||
import com.sk89q.worldguard.protection.ApplicableRegionSet;
|
||||
import com.sk89q.worldguard.protection.flags.DefaultFlag;
|
||||
import com.sk89q.worldguard.protection.flags.StateFlag;
|
||||
import com.sk89q.worldguard.protection.flags.StateFlag.State;
|
||||
import com.sk89q.worldguard.session.MoveType;
|
||||
import com.sk89q.worldguard.session.Session;
|
||||
import org.bukkit.Location;
|
||||
import org.bukkit.entity.Player;
|
||||
|
||||
public class ExitFlag extends FlagValueChangeHandler<State> {
|
||||
|
||||
private static final long MESSAGE_THRESHOLD = 1000 * 2;
|
||||
private String storedMessage;
|
||||
private boolean exitViaTeleport = false;
|
||||
private long lastMessage;
|
||||
|
||||
public ExitFlag(Session session) {
|
||||
super(session, DefaultFlag.EXIT);
|
||||
}
|
||||
|
||||
private void update(LocalPlayer localPlayer, ApplicableRegionSet set, boolean allowed) {
|
||||
if (!allowed) {
|
||||
storedMessage = set.queryValue(localPlayer, DefaultFlag.EXIT_DENY_MESSAGE);
|
||||
exitViaTeleport = set.testState(localPlayer, DefaultFlag.EXIT_VIA_TELEPORT);
|
||||
}
|
||||
}
|
||||
|
||||
private void sendMessage(Player player) {
|
||||
long now = System.currentTimeMillis();
|
||||
|
||||
if ((now - lastMessage) > MESSAGE_THRESHOLD && storedMessage != null && !storedMessage.isEmpty()) {
|
||||
player.sendMessage(CommandUtils.replaceColorMacros(storedMessage));
|
||||
lastMessage = now;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onInitialValue(Player player, ApplicableRegionSet set, State value) {
|
||||
update(getPlugin().wrapPlayer(player), set, StateFlag.test(value));
|
||||
}
|
||||
|
||||
@Override
|
||||
protected boolean onSetValue(Player player, Location from, Location to, ApplicableRegionSet toSet, State currentValue, State lastValue, MoveType moveType) {
|
||||
if (getSession().getManager().hasBypass(player, from.getWorld())) {
|
||||
return true;
|
||||
}
|
||||
|
||||
boolean lastAllowed = StateFlag.test(lastValue);
|
||||
boolean allowed = StateFlag.test(currentValue);
|
||||
|
||||
LocalPlayer localPlayer = getPlugin().wrapPlayer(player);
|
||||
|
||||
if (allowed && !lastAllowed && !(moveType.isTeleport() && exitViaTeleport) && moveType.isCancellable()) {
|
||||
Boolean override = toSet.queryValue(localPlayer, DefaultFlag.EXIT_OVERRIDE);
|
||||
if (override == null || !override) {
|
||||
sendMessage(player);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
update(localPlayer, toSet, allowed);
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected boolean onAbsentValue(Player player, Location from, Location to, ApplicableRegionSet toSet, State lastValue, MoveType moveType) {
|
||||
if (getSession().getManager().hasBypass(player, from.getWorld())) {
|
||||
return true;
|
||||
}
|
||||
|
||||
boolean lastAllowed = StateFlag.test(lastValue);
|
||||
|
||||
if (!lastAllowed && moveType.isCancellable()) {
|
||||
Boolean override = toSet.queryValue(getPlugin().wrapPlayer(player), DefaultFlag.EXIT_OVERRIDE);
|
||||
if (override == null || !override) {
|
||||
sendMessage(player);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,81 @@
|
||||
/*
|
||||
* 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.session.handler;
|
||||
|
||||
import com.google.common.collect.Sets;
|
||||
import com.sk89q.worldguard.bukkit.commands.CommandUtils;
|
||||
import com.sk89q.worldguard.protection.ApplicableRegionSet;
|
||||
import com.sk89q.worldguard.protection.flags.DefaultFlag;
|
||||
import com.sk89q.worldguard.protection.regions.ProtectedRegion;
|
||||
import com.sk89q.worldguard.session.MoveType;
|
||||
import com.sk89q.worldguard.session.Session;
|
||||
import org.bukkit.Location;
|
||||
import org.bukkit.entity.Player;
|
||||
|
||||
import java.util.Collections;
|
||||
import java.util.Set;
|
||||
|
||||
public class FarewellFlag extends Handler {
|
||||
|
||||
private Set<String> lastMessageStack = Collections.emptySet();
|
||||
|
||||
public FarewellFlag(Session session) {
|
||||
super(session);
|
||||
}
|
||||
|
||||
private Set<String> getMessages(Player player, ApplicableRegionSet set) {
|
||||
return Sets.newLinkedHashSet(set.queryAllValues(getPlugin().wrapPlayer(player), DefaultFlag.FAREWELL_MESSAGE));
|
||||
}
|
||||
|
||||
@Override
|
||||
public void initialize(Player player, Location current, ApplicableRegionSet set) {
|
||||
lastMessageStack = getMessages(player, set);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean onCrossBoundary(Player player, Location from, Location to, ApplicableRegionSet toSet, Set<ProtectedRegion> entered, Set<ProtectedRegion> exited, MoveType moveType) {
|
||||
Set<String> messages = getMessages(player, toSet);
|
||||
|
||||
if (!messages.isEmpty()) {
|
||||
// Due to flag priorities, we have to collect the lower
|
||||
// priority flag values separately
|
||||
for (ProtectedRegion region : toSet) {
|
||||
String message = region.getFlag(DefaultFlag.FAREWELL_MESSAGE);
|
||||
if (message != null) {
|
||||
messages.add(message);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
for (String message : lastMessageStack) {
|
||||
if (!messages.contains(message)) {
|
||||
String effective = CommandUtils.replaceColorMacros(message);
|
||||
effective = getPlugin().replaceMacros(player, effective);
|
||||
player.sendMessage(effective.replaceAll("\\\\n", "\n").split("\\n"));
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
lastMessageStack = messages;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,83 @@
|
||||
/*
|
||||
* 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.session.handler;
|
||||
|
||||
import com.sk89q.worldguard.LocalPlayer;
|
||||
import com.sk89q.worldguard.protection.ApplicableRegionSet;
|
||||
import com.sk89q.worldguard.protection.flags.DefaultFlag;
|
||||
import com.sk89q.worldguard.session.Session;
|
||||
import org.bukkit.GameMode;
|
||||
import org.bukkit.entity.Player;
|
||||
|
||||
public class FeedFlag extends Handler {
|
||||
|
||||
private long lastFeed = 0;
|
||||
|
||||
public FeedFlag(Session session) {
|
||||
super(session);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void tick(Player player, ApplicableRegionSet set) {
|
||||
long now = System.currentTimeMillis();
|
||||
LocalPlayer localPlayer = getSession().getPlugin().wrapPlayer(player);
|
||||
|
||||
Integer feedAmount = set.queryValue(localPlayer, DefaultFlag.FEED_AMOUNT);
|
||||
Integer feedDelay = set.queryValue(localPlayer, DefaultFlag.FEED_DELAY);
|
||||
Integer minHunger = set.queryValue(localPlayer, DefaultFlag.MIN_FOOD);
|
||||
Integer maxHunger = set.queryValue(localPlayer, DefaultFlag.MAX_FOOD);
|
||||
|
||||
if (feedAmount == null || feedDelay == null || feedAmount == 0 || feedDelay < 0) {
|
||||
return;
|
||||
}
|
||||
if (feedAmount < 0
|
||||
&& (getSession().isInvincible(player)
|
||||
|| (player.getGameMode() != GameMode.SURVIVAL && player.getGameMode() != GameMode.ADVENTURE))) {
|
||||
// don't starve invincible players
|
||||
return;
|
||||
}
|
||||
if (minHunger == null) {
|
||||
minHunger = 0;
|
||||
}
|
||||
if (maxHunger == null) {
|
||||
maxHunger = 20;
|
||||
}
|
||||
|
||||
// Apply a cap to prevent possible exceptions
|
||||
minHunger = Math.min(20, minHunger);
|
||||
maxHunger = Math.min(20, maxHunger);
|
||||
|
||||
if (player.getFoodLevel() >= maxHunger && feedAmount > 0) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (feedDelay <= 0) {
|
||||
player.setFoodLevel(feedAmount > 0 ? maxHunger : minHunger);
|
||||
player.setSaturation(player.getFoodLevel());
|
||||
lastFeed = now;
|
||||
} else if (now - lastFeed > feedDelay * 1000) {
|
||||
// clamp health between minimum and maximum
|
||||
player.setFoodLevel(Math.min(maxHunger, Math.max(minHunger, player.getFoodLevel() + feedAmount)));
|
||||
player.setSaturation(player.getFoodLevel());
|
||||
lastFeed = now;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,72 @@
|
||||
/*
|
||||
* WorldGuard, a suite of tools for Minecraft
|
||||
* Copyright (C) sk89q <http://www.sk89q.com>
|
||||
* Copyright (C) WorldGuard team and contributors
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify it
|
||||
* under the terms of the GNU Lesser General Public License as published by the
|
||||
* Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License
|
||||
* for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
package com.sk89q.worldguard.session.handler;
|
||||
|
||||
import com.sk89q.worldguard.protection.ApplicableRegionSet;
|
||||
import com.sk89q.worldguard.protection.flags.Flag;
|
||||
import com.sk89q.worldguard.protection.regions.ProtectedRegion;
|
||||
import com.sk89q.worldguard.session.MoveType;
|
||||
import com.sk89q.worldguard.session.Session;
|
||||
import org.bukkit.Location;
|
||||
import org.bukkit.entity.Player;
|
||||
|
||||
import java.util.Set;
|
||||
|
||||
public abstract class FlagValueChangeHandler<T> extends Handler {
|
||||
|
||||
private final Flag<T> flag;
|
||||
private T lastValue;
|
||||
|
||||
protected FlagValueChangeHandler(Session session, Flag<T> flag) {
|
||||
super(session);
|
||||
this.flag = flag;
|
||||
}
|
||||
|
||||
@Override
|
||||
public final void initialize(Player player, Location current, ApplicableRegionSet set) {
|
||||
lastValue = set.queryValue(getPlugin().wrapPlayer(player), flag);
|
||||
onInitialValue(player, set, lastValue);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean onCrossBoundary(Player player, Location from, Location to, ApplicableRegionSet toSet, Set<ProtectedRegion> entered, Set<ProtectedRegion> exited, MoveType moveType) {
|
||||
T currentValue = toSet.queryValue(getPlugin().wrapPlayer(player), flag);
|
||||
boolean allowed = true;
|
||||
|
||||
if (currentValue == null && lastValue != null) {
|
||||
allowed = onAbsentValue(player, from, to, toSet, lastValue, moveType);
|
||||
} else if (currentValue != null && currentValue != lastValue) {
|
||||
allowed = onSetValue(player, from, to, toSet, currentValue, lastValue, moveType);
|
||||
}
|
||||
|
||||
if (allowed) {
|
||||
lastValue = currentValue;
|
||||
}
|
||||
|
||||
return allowed;
|
||||
}
|
||||
|
||||
protected abstract void onInitialValue(Player player, ApplicableRegionSet set, T value);
|
||||
|
||||
protected abstract boolean onSetValue(Player player, Location from, Location to, ApplicableRegionSet toSet, T currentValue, T lastValue, MoveType moveType);
|
||||
|
||||
protected abstract boolean onAbsentValue(Player player, Location from, Location to, ApplicableRegionSet toSet, T lastValue, MoveType moveType);
|
||||
|
||||
}
|
||||
@@ -0,0 +1,84 @@
|
||||
/*
|
||||
* 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.session.handler;
|
||||
|
||||
import com.sk89q.worldguard.protection.ApplicableRegionSet;
|
||||
import com.sk89q.worldguard.protection.flags.DefaultFlag;
|
||||
import com.sk89q.worldguard.session.MoveType;
|
||||
import com.sk89q.worldguard.session.Session;
|
||||
import org.bukkit.GameMode;
|
||||
import org.bukkit.Location;
|
||||
import org.bukkit.World;
|
||||
import org.bukkit.entity.Player;
|
||||
|
||||
import javax.annotation.Nullable;
|
||||
|
||||
public class GameModeFlag extends FlagValueChangeHandler<GameMode> {
|
||||
|
||||
private GameMode originalGameMode;
|
||||
private GameMode setGameMode;
|
||||
|
||||
public GameModeFlag(Session session) {
|
||||
super(session, DefaultFlag.GAME_MODE);
|
||||
}
|
||||
|
||||
public GameMode getOriginalGameMode() {
|
||||
return originalGameMode;
|
||||
}
|
||||
|
||||
public GameMode getSetGameMode() {
|
||||
return setGameMode;
|
||||
}
|
||||
|
||||
private void updateGameMode(Player player, @Nullable GameMode newValue, World world) {
|
||||
if (!getSession().getManager().hasBypass(player, world) && newValue != null) {
|
||||
if (player.getGameMode() != newValue) {
|
||||
originalGameMode = player.getGameMode();
|
||||
player.setGameMode(newValue);
|
||||
} else if (originalGameMode == null) {
|
||||
originalGameMode = player.getServer().getDefaultGameMode();
|
||||
}
|
||||
} else {
|
||||
if (originalGameMode != null) {
|
||||
GameMode mode = originalGameMode;
|
||||
originalGameMode = null;
|
||||
player.setGameMode(mode);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onInitialValue(Player player, ApplicableRegionSet set, GameMode value) {
|
||||
updateGameMode(player, value, player.getWorld());
|
||||
}
|
||||
|
||||
@Override
|
||||
protected boolean onSetValue(Player player, Location from, Location to, ApplicableRegionSet toSet, GameMode currentValue, GameMode lastValue, MoveType moveType) {
|
||||
updateGameMode(player, currentValue, to.getWorld());
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected boolean onAbsentValue(Player player, Location from, Location to, ApplicableRegionSet toSet, GameMode lastValue, MoveType moveType) {
|
||||
updateGameMode(player, null, player.getWorld());
|
||||
return true;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,76 @@
|
||||
/*
|
||||
* WorldGuard, a suite of tools for Minecraft
|
||||
* Copyright (C) sk89q <http://www.sk89q.com>
|
||||
* Copyright (C) WorldGuard team and contributors
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify it
|
||||
* under the terms of the GNU Lesser General Public License as published by the
|
||||
* Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License
|
||||
* for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
package com.sk89q.worldguard.session.handler;
|
||||
|
||||
import com.sk89q.commandbook.CommandBook;
|
||||
import com.sk89q.commandbook.GodComponent;
|
||||
import com.sk89q.worldguard.protection.flags.StateFlag.State;
|
||||
import com.sk89q.worldguard.session.Session;
|
||||
import org.bukkit.entity.Player;
|
||||
|
||||
import javax.annotation.Nullable;
|
||||
|
||||
public class GodMode extends Handler {
|
||||
|
||||
private boolean godMode;
|
||||
|
||||
public GodMode(Session session) {
|
||||
super(session);
|
||||
}
|
||||
|
||||
public boolean hasGodMode(Player player) {
|
||||
if (getPlugin().getGlobalStateManager().hasCommandBookGodMode()) {
|
||||
GodComponent god = CommandBook.inst().getComponentManager().getComponent(GodComponent.class);
|
||||
if (god != null) {
|
||||
return god.hasGodMode(player);
|
||||
}
|
||||
}
|
||||
|
||||
return godMode;
|
||||
}
|
||||
|
||||
public void setGodMode(Player player, boolean godMode) {
|
||||
if (getPlugin().getGlobalStateManager().hasCommandBookGodMode()) {
|
||||
GodComponent god = CommandBook.inst().getComponentManager().getComponent(GodComponent.class);
|
||||
if (god != null) {
|
||||
god.enableGodMode(player);
|
||||
}
|
||||
}
|
||||
|
||||
this.godMode = godMode;
|
||||
}
|
||||
|
||||
@Nullable
|
||||
@Override
|
||||
public State getInvincibility(Player player) {
|
||||
return hasGodMode(player) ? State.ALLOW : null;
|
||||
}
|
||||
|
||||
public static boolean set(Player player, Session session, boolean value) {
|
||||
GodMode godMode = session.getHandler(GodMode.class);
|
||||
if (godMode != null) {
|
||||
godMode.setGodMode(player, value);
|
||||
return true;
|
||||
} else{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,72 @@
|
||||
/*
|
||||
* WorldGuard, a suite of tools for Minecraft
|
||||
* Copyright (C) sk89q <http://www.sk89q.com>
|
||||
* Copyright (C) WorldGuard team and contributors
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify it
|
||||
* under the terms of the GNU Lesser General Public License as published by the
|
||||
* Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License
|
||||
* for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
package com.sk89q.worldguard.session.handler;
|
||||
|
||||
import com.google.common.collect.Sets;
|
||||
import com.sk89q.worldguard.bukkit.commands.CommandUtils;
|
||||
import com.sk89q.worldguard.protection.ApplicableRegionSet;
|
||||
import com.sk89q.worldguard.protection.flags.DefaultFlag;
|
||||
import com.sk89q.worldguard.protection.regions.ProtectedRegion;
|
||||
import com.sk89q.worldguard.session.MoveType;
|
||||
import com.sk89q.worldguard.session.Session;
|
||||
import org.bukkit.Location;
|
||||
import org.bukkit.entity.Player;
|
||||
|
||||
import java.util.Collection;
|
||||
import java.util.Collections;
|
||||
import java.util.Set;
|
||||
|
||||
public class GreetingFlag extends Handler {
|
||||
|
||||
private Set<String> lastMessageStack = Collections.emptySet();
|
||||
|
||||
public GreetingFlag(Session session) {
|
||||
super(session);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean onCrossBoundary(Player player, Location from, Location to, ApplicableRegionSet toSet, Set<ProtectedRegion> entered, Set<ProtectedRegion> exited, MoveType moveType) {
|
||||
Collection<String> messages = toSet.queryAllValues(getPlugin().wrapPlayer(player), DefaultFlag.GREET_MESSAGE);
|
||||
|
||||
for (String message : messages) {
|
||||
if (!lastMessageStack.contains(message)) {
|
||||
String effective = CommandUtils.replaceColorMacros(message);
|
||||
effective = getPlugin().replaceMacros(player, effective);
|
||||
player.sendMessage(effective.replaceAll("\\\\n", "\n").split("\\n"));
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
lastMessageStack = Sets.newHashSet(messages);
|
||||
|
||||
if (!lastMessageStack.isEmpty()) {
|
||||
// Due to flag priorities, we have to collect the lower
|
||||
// priority flag values separately
|
||||
for (ProtectedRegion region : toSet) {
|
||||
String message = region.getFlag(DefaultFlag.GREET_MESSAGE);
|
||||
if (message != null) {
|
||||
lastMessageStack.add(message);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,148 @@
|
||||
/*
|
||||
* 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.session.handler;
|
||||
|
||||
import com.sk89q.worldguard.bukkit.WorldGuardPlugin;
|
||||
import com.sk89q.worldguard.protection.ApplicableRegionSet;
|
||||
import com.sk89q.worldguard.protection.flags.StateFlag.State;
|
||||
import com.sk89q.worldguard.protection.regions.ProtectedRegion;
|
||||
import com.sk89q.worldguard.session.MoveType;
|
||||
import com.sk89q.worldguard.session.Session;
|
||||
import com.sk89q.worldguard.session.SessionManager;
|
||||
import org.bukkit.Location;
|
||||
import org.bukkit.entity.Player;
|
||||
|
||||
import javax.annotation.Nullable;
|
||||
import java.util.Set;
|
||||
|
||||
import static com.google.common.base.Preconditions.checkNotNull;
|
||||
|
||||
/**
|
||||
* Stores session data and possibly acts on it.
|
||||
*/
|
||||
public abstract class Handler {
|
||||
|
||||
private final Session session;
|
||||
|
||||
/**
|
||||
* Create a new handler.
|
||||
*
|
||||
* @param session The session
|
||||
*/
|
||||
protected Handler(Session session) {
|
||||
checkNotNull(session, "session");
|
||||
this.session = session;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the plugin.
|
||||
*
|
||||
* @return The plugin
|
||||
*/
|
||||
public WorldGuardPlugin getPlugin() {
|
||||
return getSession().getManager().getPlugin();
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the session.
|
||||
*
|
||||
* @return The session
|
||||
*/
|
||||
public Session getSession() {
|
||||
return session;
|
||||
}
|
||||
|
||||
/**
|
||||
* Called when the session is first being created or
|
||||
* {@code /wg flushstates} is used.
|
||||
*
|
||||
* @param player The player
|
||||
* @param current The player's current location
|
||||
* @param set The regions for the current location
|
||||
*/
|
||||
public void initialize(Player player, Location current, ApplicableRegionSet set) {
|
||||
}
|
||||
|
||||
/**
|
||||
* Called when {@link Session#testMoveTo(Player, Location, MoveType)} is called.
|
||||
*
|
||||
* <p>If this method returns {@code false}, then no other handlers
|
||||
* will be run (for this move attempt).</p>
|
||||
*
|
||||
* @param player The player
|
||||
* @param from The previous, valid, location
|
||||
* @param to The new location to test
|
||||
* @param toSet The regions for the new location
|
||||
* @param moveType The type of movement
|
||||
* @return Whether the movement should be allowed
|
||||
*/
|
||||
public boolean testMoveTo(Player player, Location from, Location to, ApplicableRegionSet toSet, MoveType moveType) {
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Called when a player has moved into a new location where either
|
||||
* there are fewer regions or more regions.
|
||||
*
|
||||
* <p>This is called only if the move test
|
||||
* ({@link Session#testMoveTo(Player, Location, MoveType)}) was successful.</p>
|
||||
*
|
||||
* <p>If this method returns {@code false}, then no other handlers
|
||||
* will be run (for this move attempt).</p>
|
||||
*
|
||||
* @param player The player
|
||||
* @param from The previous, valid, location
|
||||
* @param to The new location to test
|
||||
* @param toSet The regions for the new location
|
||||
* @param entered The list of regions that have been entered
|
||||
* @param exited The list of regions that have been left
|
||||
* @param moveType The type of move
|
||||
* @return Whether the movement should be allowed
|
||||
*/
|
||||
public boolean onCrossBoundary(Player player, Location from, Location to, ApplicableRegionSet toSet,
|
||||
Set<ProtectedRegion> entered, Set<ProtectedRegion> exited, MoveType moveType) {
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Called periodically (at least once every second) by
|
||||
* {@link SessionManager} in the server's main thread.
|
||||
*
|
||||
* @param player The player
|
||||
* @param set The regions for the player's current location
|
||||
*/
|
||||
public void tick(Player player, ApplicableRegionSet set) {
|
||||
}
|
||||
|
||||
/**
|
||||
* Return whether the player should be invincible.
|
||||
*
|
||||
* <p>{@link State#DENY} can be returned to prevent invincibility
|
||||
* even if another handler permits it.</p>
|
||||
*
|
||||
* @param player The player
|
||||
* @return Invincibility state
|
||||
*/
|
||||
@Nullable
|
||||
public State getInvincibility(Player player) {
|
||||
return null;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,86 @@
|
||||
/*
|
||||
* 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.session.handler;
|
||||
|
||||
import com.sk89q.worldguard.LocalPlayer;
|
||||
import com.sk89q.worldguard.protection.ApplicableRegionSet;
|
||||
import com.sk89q.worldguard.protection.flags.DefaultFlag;
|
||||
import com.sk89q.worldguard.session.Session;
|
||||
import org.bukkit.GameMode;
|
||||
import org.bukkit.entity.Player;
|
||||
|
||||
public class HealFlag extends Handler {
|
||||
|
||||
private long lastHeal = 0;
|
||||
|
||||
public HealFlag(Session session) {
|
||||
super(session);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void tick(Player player, ApplicableRegionSet set) {
|
||||
LocalPlayer localPlayer = getPlugin().wrapPlayer(player);
|
||||
|
||||
if (player.getHealth() <= 0) {
|
||||
return;
|
||||
}
|
||||
|
||||
long now = System.currentTimeMillis();
|
||||
|
||||
Integer healAmount = set.queryValue(localPlayer, DefaultFlag.HEAL_AMOUNT);
|
||||
Integer healDelay = set.queryValue(localPlayer, DefaultFlag.HEAL_DELAY);
|
||||
Double minHealth = set.queryValue(localPlayer, DefaultFlag.MIN_HEAL);
|
||||
Double maxHealth = set.queryValue(localPlayer, DefaultFlag.MAX_HEAL);
|
||||
|
||||
if (healAmount == null || healDelay == null || healAmount == 0 || healDelay < 0) {
|
||||
return;
|
||||
}
|
||||
if (healAmount < 0
|
||||
&& (getSession().isInvincible(player)
|
||||
|| (player.getGameMode() != GameMode.SURVIVAL && player.getGameMode() != GameMode.ADVENTURE))) {
|
||||
// don't damage invincible players
|
||||
return;
|
||||
}
|
||||
if (minHealth == null) {
|
||||
minHealth = 0.0;
|
||||
}
|
||||
if (maxHealth == null) {
|
||||
maxHealth = player.getMaxHealth();
|
||||
}
|
||||
|
||||
// Apply a cap to prevent possible exceptions
|
||||
minHealth = Math.min(player.getMaxHealth(), minHealth);
|
||||
maxHealth = Math.min(player.getMaxHealth(), maxHealth);
|
||||
|
||||
if (player.getHealth() >= maxHealth && healAmount > 0) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (healDelay <= 0) {
|
||||
player.setHealth(healAmount > 0 ? maxHealth : minHealth); // this will insta-kill if the flag is unset
|
||||
lastHeal = now;
|
||||
} else if (now - lastHeal > healDelay * 1000) {
|
||||
// clamp health between minimum and maximum
|
||||
player.setHealth(Math.min(maxHealth, Math.max(minHealth, player.getHealth() + healAmount)));
|
||||
lastHeal = now;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,68 @@
|
||||
/*
|
||||
* WorldGuard, a suite of tools for Minecraft
|
||||
* Copyright (C) sk89q <http://www.sk89q.com>
|
||||
* Copyright (C) WorldGuard team and contributors
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify it
|
||||
* under the terms of the GNU Lesser General Public License as published by the
|
||||
* Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License
|
||||
* for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
package com.sk89q.worldguard.session.handler;
|
||||
|
||||
import com.sk89q.worldguard.protection.ApplicableRegionSet;
|
||||
import com.sk89q.worldguard.protection.flags.DefaultFlag;
|
||||
import com.sk89q.worldguard.protection.flags.StateFlag.State;
|
||||
import com.sk89q.worldguard.session.MoveType;
|
||||
import com.sk89q.worldguard.session.Session;
|
||||
import org.bukkit.Location;
|
||||
import org.bukkit.entity.Player;
|
||||
|
||||
import javax.annotation.Nullable;
|
||||
|
||||
public class InvincibilityFlag extends FlagValueChangeHandler<State> {
|
||||
|
||||
@Nullable
|
||||
private State invincibility;
|
||||
|
||||
public InvincibilityFlag(Session session) {
|
||||
super(session, DefaultFlag.INVINCIBILITY);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onInitialValue(Player player, ApplicableRegionSet set, State value) {
|
||||
invincibility = value;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected boolean onSetValue(Player player, Location from, Location to, ApplicableRegionSet toSet, State currentValue, State lastValue, MoveType moveType) {
|
||||
invincibility = currentValue;
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected boolean onAbsentValue(Player player, Location from, Location to, ApplicableRegionSet toSet, State lastValue, MoveType moveType) {
|
||||
invincibility = null;
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
@Nullable
|
||||
public State getInvincibility(Player player) {
|
||||
if (invincibility == State.DENY && getPlugin().hasPermission(player, "worldguard.god.override-regions")) {
|
||||
return null;
|
||||
}
|
||||
|
||||
return invincibility;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,68 @@
|
||||
/*
|
||||
* WorldGuard, a suite of tools for Minecraft
|
||||
* Copyright (C) sk89q <http://www.sk89q.com>
|
||||
* Copyright (C) WorldGuard team and contributors
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify it
|
||||
* under the terms of the GNU Lesser General Public License as published by the
|
||||
* Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License
|
||||
* for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
package com.sk89q.worldguard.session.handler;
|
||||
|
||||
import com.sk89q.worldguard.protection.ApplicableRegionSet;
|
||||
import com.sk89q.worldguard.protection.flags.DefaultFlag;
|
||||
import com.sk89q.worldguard.protection.regions.ProtectedRegion;
|
||||
import com.sk89q.worldguard.session.MoveType;
|
||||
import com.sk89q.worldguard.session.Session;
|
||||
import org.bukkit.ChatColor;
|
||||
import org.bukkit.Location;
|
||||
import org.bukkit.entity.Player;
|
||||
|
||||
public class NotifyEntryFlag extends FlagValueChangeHandler<Boolean> {
|
||||
|
||||
public NotifyEntryFlag(Session session) {
|
||||
super(session, DefaultFlag.NOTIFY_ENTER);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onInitialValue(Player player, ApplicableRegionSet set, Boolean value) {
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
protected boolean onSetValue(Player player, Location from, Location to, ApplicableRegionSet toSet, Boolean currentValue, Boolean lastValue, MoveType moveType) {
|
||||
StringBuilder regionList = new StringBuilder();
|
||||
|
||||
for (ProtectedRegion region : toSet) {
|
||||
if (regionList.length() != 0) {
|
||||
regionList.append(", ");
|
||||
}
|
||||
|
||||
regionList.append(region.getId());
|
||||
}
|
||||
|
||||
getPlugin().broadcastNotification(ChatColor.GRAY + "WG: "
|
||||
+ ChatColor.LIGHT_PURPLE + player.getName()
|
||||
+ ChatColor.GOLD + " entered NOTIFY region: "
|
||||
+ ChatColor.WHITE
|
||||
+ regionList);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected boolean onAbsentValue(Player player, Location from, Location to, ApplicableRegionSet toSet, Boolean lastValue, MoveType moveType) {
|
||||
return true;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,55 @@
|
||||
/*
|
||||
* 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.session.handler;
|
||||
|
||||
import com.sk89q.worldguard.protection.ApplicableRegionSet;
|
||||
import com.sk89q.worldguard.protection.flags.DefaultFlag;
|
||||
import com.sk89q.worldguard.session.MoveType;
|
||||
import com.sk89q.worldguard.session.Session;
|
||||
import org.bukkit.ChatColor;
|
||||
import org.bukkit.Location;
|
||||
import org.bukkit.entity.Player;
|
||||
|
||||
public class NotifyExitFlag extends FlagValueChangeHandler<Boolean> {
|
||||
|
||||
private Boolean notifiedForLeave = false;
|
||||
|
||||
public NotifyExitFlag(Session session) {
|
||||
super(session, DefaultFlag.NOTIFY_LEAVE);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onInitialValue(Player player, ApplicableRegionSet set, Boolean value) {
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
protected boolean onSetValue(Player player, Location from, Location to, ApplicableRegionSet toSet, Boolean currentValue, Boolean lastValue, MoveType moveType) {
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected boolean onAbsentValue(Player player, Location from, Location to, ApplicableRegionSet toSet, Boolean lastValue, MoveType moveType) {
|
||||
getPlugin().broadcastNotification(ChatColor.GRAY + "WG: "
|
||||
+ ChatColor.LIGHT_PURPLE + player.getName()
|
||||
+ ChatColor.GOLD + " left NOTIFY region");
|
||||
return true;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,86 @@
|
||||
/*
|
||||
* 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.session.handler;
|
||||
|
||||
import com.sk89q.worldguard.protection.ApplicableRegionSet;
|
||||
import com.sk89q.worldguard.protection.flags.DefaultFlag;
|
||||
import com.sk89q.worldguard.session.MoveType;
|
||||
import com.sk89q.worldguard.session.Session;
|
||||
import org.bukkit.Location;
|
||||
import org.bukkit.entity.Player;
|
||||
|
||||
import javax.annotation.Nullable;
|
||||
import java.util.regex.Pattern;
|
||||
|
||||
public class TimeLockFlag extends FlagValueChangeHandler<String> {
|
||||
|
||||
private Long time;
|
||||
private boolean relative;
|
||||
private Long initialTime;
|
||||
private boolean initialRelative;
|
||||
|
||||
Pattern timePattern = Pattern.compile("(\\+|-)?\\d+");
|
||||
|
||||
public TimeLockFlag(Session session) {
|
||||
super(session, DefaultFlag.TIME_LOCK);
|
||||
}
|
||||
|
||||
private void updatePlayerTime(Player player, @Nullable String value) {
|
||||
// store settings, regardless of if we change anything
|
||||
initialRelative = player.isPlayerTimeRelative();
|
||||
initialTime = player.getPlayerTime();
|
||||
if (value == null || !timePattern.matcher(value).matches()) {
|
||||
// invalid input
|
||||
return;
|
||||
}
|
||||
if (value.startsWith("+") || value.startsWith("-")) {
|
||||
relative = true;
|
||||
} else {
|
||||
relative = false;
|
||||
}
|
||||
time = Long.valueOf(value);
|
||||
if (!relative && (time < 0L || time > 24000L)) { // invalid time, reset to 0
|
||||
time = 0L;
|
||||
}
|
||||
player.setPlayerTime(time, relative);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onInitialValue(Player player, ApplicableRegionSet set, String value) {
|
||||
initialTime = player.getPlayerTime();
|
||||
initialRelative = player.isPlayerTimeRelative();
|
||||
updatePlayerTime(player, value);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected boolean onSetValue(Player player, Location from, Location to, ApplicableRegionSet toSet, String currentValue, String lastValue, MoveType moveType) {
|
||||
updatePlayerTime(player, currentValue);
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected boolean onAbsentValue(Player player, Location from, Location to, ApplicableRegionSet toSet, String lastValue, MoveType moveType) {
|
||||
player.setPlayerTime(initialTime, initialRelative);
|
||||
initialRelative = true;
|
||||
initialTime = 0L;
|
||||
return true;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,51 @@
|
||||
/*
|
||||
* 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.session.handler;
|
||||
|
||||
import com.sk89q.worldguard.session.Session;
|
||||
import org.bukkit.entity.Player;
|
||||
|
||||
public class WaterBreathing extends Handler {
|
||||
|
||||
public boolean waterBreathing;
|
||||
|
||||
public WaterBreathing(Session session) {
|
||||
super(session);
|
||||
}
|
||||
|
||||
public boolean hasWaterBreathing() {
|
||||
return waterBreathing;
|
||||
}
|
||||
|
||||
public void setWaterBreathing(boolean waterBreathing) {
|
||||
this.waterBreathing = waterBreathing;
|
||||
}
|
||||
|
||||
public static boolean set(Player player, Session session, boolean value) {
|
||||
WaterBreathing waterBreathing = session.getHandler(WaterBreathing.class);
|
||||
if (waterBreathing != null) {
|
||||
waterBreathing.setWaterBreathing(value);
|
||||
return true;
|
||||
} else{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,71 @@
|
||||
/*
|
||||
* 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.session.handler;
|
||||
|
||||
import com.sk89q.worldguard.protection.ApplicableRegionSet;
|
||||
import com.sk89q.worldguard.protection.flags.DefaultFlag;
|
||||
import com.sk89q.worldguard.session.MoveType;
|
||||
import com.sk89q.worldguard.session.Session;
|
||||
import org.bukkit.Location;
|
||||
import org.bukkit.WeatherType;
|
||||
import org.bukkit.entity.Player;
|
||||
|
||||
import javax.annotation.Nullable;
|
||||
|
||||
public class WeatherLockFlag extends FlagValueChangeHandler<WeatherType> {
|
||||
|
||||
private WeatherType initialWeather;
|
||||
|
||||
public WeatherLockFlag(Session session) {
|
||||
super(session, DefaultFlag.WEATHER_LOCK);
|
||||
}
|
||||
|
||||
private void updatePlayerWeather(Player player, @Nullable WeatherType value) {
|
||||
initialWeather = player.getPlayerWeather();
|
||||
player.setPlayerWeather(value);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onInitialValue(Player player, ApplicableRegionSet set, WeatherType value) {
|
||||
if (value == null) {
|
||||
initialWeather = null;
|
||||
return;
|
||||
}
|
||||
updatePlayerWeather(player, value);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected boolean onSetValue(Player player, Location from, Location to, ApplicableRegionSet toSet, WeatherType currentValue, WeatherType lastValue, MoveType moveType) {
|
||||
updatePlayerWeather(player, currentValue);
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected boolean onAbsentValue(Player player, Location from, Location to, ApplicableRegionSet toSet, WeatherType lastValue, MoveType moveType) {
|
||||
if (initialWeather != null) {
|
||||
player.setPlayerWeather(initialWeather);
|
||||
} else {
|
||||
player.resetPlayerWeather();
|
||||
}
|
||||
initialWeather = null;
|
||||
return true;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -64,7 +64,7 @@ public class CommandFilter implements Predicate<String> {
|
||||
@SuppressWarnings("StatementWithEmptyBody")
|
||||
@Override
|
||||
public boolean apply(String command) {
|
||||
command = command.toLowerCase().replaceAll("^/([^:]*:)?", "/");
|
||||
command = command.toLowerCase().replaceAll("^/([^ :]*:)?", "/");
|
||||
|
||||
/*
|
||||
* denied used allow?
|
||||
|
||||
@@ -0,0 +1,124 @@
|
||||
/*
|
||||
* 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.util.logging;
|
||||
|
||||
import com.google.common.base.Strings;
|
||||
import com.google.common.collect.Maps;
|
||||
import org.bukkit.plugin.Plugin;
|
||||
|
||||
import javax.annotation.Nullable;
|
||||
import java.security.CodeSource;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.logging.Level;
|
||||
import java.util.logging.Logger;
|
||||
|
||||
import static com.google.common.base.Preconditions.checkNotNull;
|
||||
|
||||
/**
|
||||
* Validates that certain specified classes came from the same source as
|
||||
* a plugin.
|
||||
*/
|
||||
public class ClassSourceValidator {
|
||||
|
||||
private static final Logger log = Logger.getLogger(ClassSourceValidator.class.getCanonicalName());
|
||||
private static final String separatorLine = Strings.repeat("*", 46);
|
||||
|
||||
private final Plugin plugin;
|
||||
@Nullable
|
||||
private final CodeSource expectedCodeSource;
|
||||
|
||||
/**
|
||||
* Create a new instance.
|
||||
*
|
||||
* @param plugin The plugin
|
||||
*/
|
||||
public ClassSourceValidator(Plugin plugin) {
|
||||
checkNotNull(plugin, "plugin");
|
||||
this.plugin = plugin;
|
||||
this.expectedCodeSource = plugin.getClass().getProtectionDomain().getCodeSource();
|
||||
}
|
||||
|
||||
/**
|
||||
* Return a map of classes that been loaded from a different source.
|
||||
*
|
||||
* @param classes A list of classes to check
|
||||
* @return The results
|
||||
*/
|
||||
public Map<Class<?>, CodeSource> findMismatches(List<Class<?>> classes) {
|
||||
checkNotNull(classes, "classes");
|
||||
|
||||
Map<Class<?>, CodeSource> mismatches = Maps.newHashMap();
|
||||
|
||||
if (expectedCodeSource != null) {
|
||||
for (Class<?> testClass : classes) {
|
||||
CodeSource testSource = testClass.getProtectionDomain().getCodeSource();
|
||||
if (!expectedCodeSource.equals(testSource)) {
|
||||
mismatches.put(testClass, testSource);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return mismatches;
|
||||
}
|
||||
|
||||
/**
|
||||
* Reports classes that have come from a different source.
|
||||
*
|
||||
* <p>The warning is emitted to the log.</p>
|
||||
*
|
||||
* @param classes The list of classes to check
|
||||
*/
|
||||
public void reportMismatches(List<Class<?>> classes) {
|
||||
Map<Class<?>, CodeSource> mismatches = findMismatches(classes);
|
||||
|
||||
if (!mismatches.isEmpty()) {
|
||||
StringBuilder builder = new StringBuilder("\n");
|
||||
|
||||
builder.append(separatorLine).append("\n");
|
||||
builder.append("** /!\\ SEVERE WARNING /!\\\n");
|
||||
builder.append("** \n");
|
||||
builder.append("** A plugin developer has copied and pasted a portion of \n");
|
||||
builder.append("** ").append(plugin.getName()).append(" into their own plugin, so rather than using\n");
|
||||
builder.append("** the version of ").append(plugin.getName()).append(" that you downloaded, you\n");
|
||||
builder.append("** will be using a broken mix of old ").append(plugin.getName()).append(" (that came\n");
|
||||
builder.append("** with the plugin) and your downloaded version. THIS MAY\n");
|
||||
builder.append("** SEVERELY BREAK ").append(plugin.getName().toUpperCase()).append(" AND ALL OF ITS FEATURES.\n");
|
||||
builder.append("**\n");
|
||||
builder.append("** This may have happened because the developer is using\n");
|
||||
builder.append("** the ").append(plugin.getName()).append(" API and thinks that including\n");
|
||||
builder.append("** ").append(plugin.getName()).append(" is necessary. However, it is not!\n");
|
||||
builder.append("**\n");
|
||||
builder.append("** Here are some files that have been overridden:\n");
|
||||
builder.append("** \n");
|
||||
for (Map.Entry<Class<?>, CodeSource> entry : mismatches.entrySet()) {
|
||||
CodeSource codeSource = entry.getValue();
|
||||
String url = codeSource != null ? codeSource.getLocation().toExternalForm() : "(unknown)";
|
||||
builder.append("** '").append(entry.getKey().getSimpleName()).append("' came from '").append(url).append("'\n");
|
||||
}
|
||||
builder.append("**\n");
|
||||
builder.append("** Please report this to the plugins' developers.\n");
|
||||
builder.append(separatorLine).append("\n");
|
||||
|
||||
log.log(Level.SEVERE, builder.toString());
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,79 @@
|
||||
/*
|
||||
* 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.util.paste;
|
||||
|
||||
import com.google.common.util.concurrent.ListenableFuture;
|
||||
import com.sk89q.worldguard.util.net.HttpRequest;
|
||||
import com.sk89q.worldguard.util.net.HttpRequest.Form;
|
||||
import org.json.simple.JSONValue;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.net.URL;
|
||||
import java.util.Map;
|
||||
import java.util.concurrent.Callable;
|
||||
import java.util.regex.Matcher;
|
||||
import java.util.regex.Pattern;
|
||||
|
||||
public class EngineHubPaste implements Paster {
|
||||
|
||||
private static final Pattern URL_PATTERN = Pattern.compile("https?://.+$");
|
||||
|
||||
@Override
|
||||
public ListenableFuture<URL> paste(String content) {
|
||||
return Pasters.getExecutor().submit(new PasteTask(content));
|
||||
}
|
||||
|
||||
private final class PasteTask implements Callable<URL> {
|
||||
private final String content;
|
||||
|
||||
private PasteTask(String content) {
|
||||
this.content = content;
|
||||
}
|
||||
|
||||
@Override
|
||||
public URL call() throws IOException, InterruptedException {
|
||||
Form form = Form.create();
|
||||
form.add("content", content);
|
||||
form.add("from", "worldguard");
|
||||
|
||||
URL url = HttpRequest.url("http://paste.enginehub.org/paste");
|
||||
String result = HttpRequest.post(url)
|
||||
.bodyForm(form)
|
||||
.execute()
|
||||
.expectResponseCode(200)
|
||||
.returnContent()
|
||||
.asString("UTF-8").trim();
|
||||
|
||||
Object object = JSONValue.parse(result);
|
||||
if (object instanceof Map) {
|
||||
@SuppressWarnings("unchecked")
|
||||
String urlString = String.valueOf(((Map<Object, Object>) object).get("url"));
|
||||
Matcher m = URL_PATTERN.matcher(urlString);
|
||||
|
||||
if (m.matches()) {
|
||||
return new URL(urlString);
|
||||
}
|
||||
}
|
||||
|
||||
throw new IOException("Failed to save paste; instead, got: " + result);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
@@ -92,19 +92,5 @@ public class Pastebin implements Paster {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public static void main(String[] args) {
|
||||
Futures.addCallback(new Pastebin().paste("hi there"), new FutureCallback<URL>() {
|
||||
@Override
|
||||
public void onSuccess(URL url) {
|
||||
System.out.println("got: " + url);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onFailure(Throwable throwable) {
|
||||
throwable.printStackTrace();
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
}
|
||||
Loaded 100 of 111 files, more files were not shown because too many files have changed in this diff.
Show more
Reference in new issue
Block a user