forked from upstream/WorldGuard
Compare commits
77
Commits
6.0.0-beta-04
...
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 |
No files matched your search
@@ -1,5 +1,67 @@
|
||||
# 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.
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
<groupId>com.sk89q</groupId>
|
||||
<artifactId>worldguard</artifactId>
|
||||
<version>6.0.0-beta-04</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>
|
||||
|
||||
@@ -92,8 +92,15 @@
|
||||
|
||||
<dependency>
|
||||
<groupId>com.sk89q.spigot</groupId>
|
||||
<artifactId>bukkit</artifactId>
|
||||
<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.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+ -->
|
||||
@@ -461,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>
|
||||
@@ -492,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>
|
||||
@@ -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() + ".");
|
||||
|
||||
@@ -27,6 +27,8 @@ 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 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.*;
|
||||
@@ -87,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.
|
||||
*
|
||||
|
||||
@@ -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();
|
||||
}
|
||||
@@ -327,8 +338,8 @@ public class WorldGuardPlugin extends JavaPlugin {
|
||||
*
|
||||
* @return The flag state manager
|
||||
*/
|
||||
public FlagStateManager getFlagStateManager() {
|
||||
return flagStateManager;
|
||||
public SessionManager getSessionManager() {
|
||||
return sessionManager;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -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.
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
@@ -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.");
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -250,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() + "\".");
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -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;
|
||||
@@ -65,9 +64,8 @@ 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;
|
||||
|
||||
@@ -244,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));
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -304,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()) {
|
||||
@@ -313,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:
|
||||
@@ -328,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, event.getAction() == Action.RIGHT_CLICK_BLOCK) || (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;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -377,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)
|
||||
@@ -420,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
|
||||
@@ -615,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;
|
||||
@@ -679,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)
|
||||
@@ -702,7 +725,9 @@ public class EventAbstractionListener extends AbstractListener {
|
||||
if (holder instanceof BlockState) {
|
||||
Events.fireToCancel(event, new UseBlockEvent(event, create(event.getPlayer()), ((BlockState) holder).getBlock()));
|
||||
} else if (holder instanceof Entity) {
|
||||
Events.fireToCancel(event, new UseEntityEvent(event, create(event.getPlayer()), (Entity) holder));
|
||||
if (!(holder instanceof Player)) {
|
||||
Events.fireToCancel(event, new UseEntityEvent(event, create(event.getPlayer()), (Entity) holder));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -827,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();
|
||||
@@ -901,6 +931,12 @@ public class EventAbstractionListener extends AbstractListener {
|
||||
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,252 +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.BukkitUtil;
|
||||
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 = BukkitUtil.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,7 +390,8 @@ public class RegionProtectionListener extends AbstractListener {
|
||||
String what;
|
||||
|
||||
/* Hostile / ambient mob override */
|
||||
if (Entities.isHostile(event.getEntity()) || Entities.isAmbient(event.getEntity()) || Entities.isNPC(event.getEntity())) {
|
||||
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";
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -424,13 +434,14 @@ public class RegionProtectionListener extends AbstractListener {
|
||||
// Block PvP like normal even if the player has an override permission
|
||||
// because (1) this is a frequent source of confusion and
|
||||
// (2) some users want to block PvP even with the bypass permission
|
||||
boolean pvp = event.getEntity() instanceof Player && playerAttacker != null;
|
||||
boolean pvp = event.getEntity() instanceof Player && playerAttacker != null && !playerAttacker.equals(event.getEntity());
|
||||
if (isWhitelisted(event.getCause(), event.getWorld(), pvp)) {
|
||||
return;
|
||||
}
|
||||
|
||||
/* Hostile / ambient mob override */
|
||||
if (Entities.isHostile(event.getEntity()) || Entities.isAmbient(event.getEntity())) {
|
||||
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";
|
||||
|
||||
@@ -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()))) {
|
||||
@@ -458,6 +470,11 @@ public class RegionProtectionListener extends AbstractListener {
|
||||
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());
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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();
|
||||
}
|
||||
|
||||
}
|
||||
@@ -46,7 +46,15 @@ public final class Materials {
|
||||
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);
|
||||
@@ -66,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);
|
||||
@@ -197,7 +208,7 @@ 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);
|
||||
@@ -241,7 +252,7 @@ public final class Materials {
|
||||
try {
|
||||
MATERIAL_FLAGS.put(Material.STANDING_BANNER, 0);
|
||||
MATERIAL_FLAGS.put(Material.WALL_BANNER, 0);
|
||||
MATERIAL_FLAGS.put(Material.DAYLIGHT_DETECTOR_INVERTED, 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);
|
||||
@@ -391,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);
|
||||
@@ -423,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);
|
||||
@@ -644,11 +677,13 @@ public final class Materials {
|
||||
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;
|
||||
@@ -720,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;
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -70,17 +70,19 @@ public class SchedulerReport extends DataReport {
|
||||
@SuppressWarnings("unchecked")
|
||||
@Nullable
|
||||
private Class<?> getTaskClass(BukkitTask task) {
|
||||
Class<?> clazz = task.getClass();
|
||||
Set<Class<?>> classes = (Set) TypeToken.of(clazz).getTypes().rawTypes();
|
||||
|
||||
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()) {
|
||||
return field.get().get(task).getClass();
|
||||
Object res = field.get().get(task);
|
||||
return res == null ? null : res.getClass();
|
||||
}
|
||||
}
|
||||
} catch (IllegalAccessException ignored) {
|
||||
} catch (NoClassDefFoundError ignored) {
|
||||
}
|
||||
|
||||
return null;
|
||||
|
||||
@@ -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();
|
||||
}
|
||||
|
||||
@@ -63,6 +63,7 @@ public class RegionResultSet extends AbstractRegionSet {
|
||||
*/
|
||||
public RegionResultSet(Set<ProtectedRegion> applicable, @Nullable ProtectedRegion globalRegion) {
|
||||
this(NormativeOrders.fromSet(applicable), globalRegion, true);
|
||||
this.regionSet = applicable;
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
+1
-1
@@ -48,7 +48,7 @@ public class RegionOverlapAssociation implements RegionAssociable {
|
||||
@Override
|
||||
public Association getAssociation(List<ProtectedRegion> regions) {
|
||||
for (ProtectedRegion region : regions) {
|
||||
if (source.contains(region)) {
|
||||
if ((region.getId().equals(ProtectedRegion.GLOBAL_REGION) && source.isEmpty()) || source.contains(region)) {
|
||||
return Association.OWNER;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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;
|
||||
|
||||
/**
|
||||
@@ -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
|
||||
};
|
||||
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -56,13 +57,17 @@ 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>();
|
||||
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
|
||||
|
||||
@@ -442,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,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());
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
@@ -40,6 +40,7 @@ public class CancelReport implements Report {
|
||||
private final List<CancelAttempt> cancels;
|
||||
private final HandlerTracer tracer;
|
||||
private final int stackTruncateLength;
|
||||
private boolean detectingPlugin = true;
|
||||
|
||||
public <T extends Event & Cancellable> CancelReport(T event, List<CancelAttempt> cancels, int stackTruncateLength) {
|
||||
checkNotNull(event, "event");
|
||||
@@ -51,6 +52,14 @@ public class CancelReport implements Report {
|
||||
this.stackTruncateLength = stackTruncateLength;
|
||||
}
|
||||
|
||||
public boolean isDetectingPlugin() {
|
||||
return detectingPlugin;
|
||||
}
|
||||
|
||||
public void setDetectingPlugin(boolean detectingPlugin) {
|
||||
this.detectingPlugin = detectingPlugin;
|
||||
}
|
||||
|
||||
private StackTraceElement[] truncateStackTrace(StackTraceElement[] elements) {
|
||||
int newLength = elements.length - stackTruncateLength;
|
||||
if (newLength <= 0) {
|
||||
@@ -87,7 +96,7 @@ public class CancelReport implements Report {
|
||||
builder.append(getCancelText(cancel.getAfter()));
|
||||
builder.append(" by ");
|
||||
|
||||
if (cause != null) {
|
||||
if (detectingPlugin && cause != null) {
|
||||
builder.append(cause.getName());
|
||||
} else {
|
||||
builder.append(" (NOT KNOWN - use the stack trace below)");
|
||||
|
||||
@@ -21,8 +21,10 @@ package com.sk89q.worldguard.util.report;
|
||||
|
||||
import com.google.common.collect.Lists;
|
||||
|
||||
import java.util.*;
|
||||
import java.util.function.UnaryOperator;
|
||||
import java.util.Collection;
|
||||
import java.util.Iterator;
|
||||
import java.util.List;
|
||||
import java.util.ListIterator;
|
||||
|
||||
public class ReportList implements Report, List<Report> {
|
||||
|
||||
@@ -103,16 +105,6 @@ public class ReportList implements Report, List<Report> {
|
||||
return reports.retainAll(c);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void replaceAll(UnaryOperator<Report> operator) {
|
||||
reports.replaceAll(operator);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void sort(Comparator<? super Report> c) {
|
||||
reports.sort(c);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void clear() {
|
||||
reports.clear();
|
||||
|
||||
Reference in new issue
Block a user