This commit is contained in:
sk89q 2014-08-22 20:54:59 -07:00
commit 7b174683ba
212 changed files with 24207 additions and 11954 deletions

View File

@ -1,3 +1,11 @@
--
-- This file only needs to be run if you are using a very old version
-- of the region database (before 2011/03/25).
--
-- Otherwise, WG knows how to update your tables automatically, as well
-- as set them up initially.
--
SET @OLD_UNIQUE_CHECKS=@@UNIQUE_CHECKS, UNIQUE_CHECKS=0;
SET @OLD_FOREIGN_KEY_CHECKS=@@FOREIGN_KEY_CHECKS, FOREIGN_KEY_CHECKS=0;
SET @OLD_SQL_MODE=@@SQL_MODE, SQL_MODE='TRADITIONAL';

79
pom.xml
View File

@ -2,7 +2,7 @@
<modelVersion>4.0.0</modelVersion>
<groupId>com.sk89q</groupId>
<artifactId>worldguard</artifactId>
<version>5.9.1-SNAPSHOT</version>
<version>6.0.0-SNAPSHOT</version>
<packaging>jar</packaging>
<!-- Project information -->
@ -78,6 +78,16 @@
<version>5.5.8</version>
<scope>compile</scope>
<type>jar</type>
<exclusions>
<exclusion>
<groupId>com.zachsthings.libcomponents</groupId>
<artifactId>libcomponents-bukkit</artifactId>
</exclusion>
<exclusion>
<groupId>org.bukkit</groupId>
<artifactId>bukkit</artifactId>
</exclusion>
</exclusions>
</dependency>
<!-- Used for running CraftBukkit from within your IDE
@ -85,7 +95,7 @@
<dependency>
<groupId>org.sk89q.bukkit</groupId>
<artifactId>bukkit-classloader-check</artifactId>
<version>1.7.2-R0.3</version>
<version>1.7.9-R0.2</version>
<scope>runtime</scope>
<type>jar</type>
<optional>true</optional>
@ -93,7 +103,7 @@
<dependency>
<groupId>org.bukkit</groupId>
<artifactId>craftbukkit</artifactId>
<version>1.7.2-R0.3</version>
<version>1.7.9-R0.2</version>
<scope>runtime</scope>
<type>jar</type>
<optional>true</optional>
@ -103,7 +113,7 @@
<dependency>
<groupId>org.bukkit</groupId>
<artifactId>bukkit</artifactId>
<version>1.7.2-R0.3</version>
<version>1.7.9-R0.2</version>
<scope>compile</scope>
<type>jar</type>
</dependency>
@ -123,6 +133,10 @@
<groupId>org.spout</groupId>
<artifactId>spoutapi</artifactId>
</exclusion>
<exclusion>
<groupId>org.bukkit</groupId>
<artifactId>bukkit</artifactId>
</exclusion>
</exclusions>
</dependency>
@ -132,6 +146,7 @@
<version>5.0</version>
<scope>compile</scope>
<type>jar</type>
<optional>true</optional>
</dependency>
<dependency>
@ -146,6 +161,8 @@
<groupId>com.google.code.findbugs</groupId>
<artifactId>jsr305</artifactId>
<version>1.3.9</version>
<scope>compile</scope>
<type>jar</type>
</dependency>
<dependency>
@ -162,14 +179,47 @@
<version>2.0</version>
<scope>compile</scope>
<type>jar</type>
<optional>true</optional>
</dependency>
<dependency>
<groupId>org.flywaydb</groupId>
<artifactId>flyway-core</artifactId>
<version>3.0</version>
<scope>compile</scope>
<type>jar</type>
<optional>true</optional>
</dependency>
<dependency>
<groupId>com.sk89q</groupId>
<artifactId>squirrelid</artifactId>
<version>0.1.0</version>
<scope>compile</scope>
<type>jar</type>
<optional>true</optional>
</dependency>
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>4.8.1</version>
<version>4.11</version>
<scope>test</scope>
<type>jar</type>
<exclusions>
<exclusion>
<groupId>org.hamcrest</groupId>
<artifactId>hamcrest-core</artifactId>
</exclusion>
</exclusions>
</dependency>
<dependency>
<groupId>org.hamcrest</groupId>
<artifactId>hamcrest-library</artifactId>
<version>1.2.1</version>
<scope>test</scope>
<optional>true</optional>
</dependency>
</dependencies>
@ -204,6 +254,11 @@
<include>blacklist.txt</include>
</includes>
</resource>
<resource>
<targetPath>migrations/</targetPath>
<filtering>false</filtering>
<directory>${basedir}/src/main/resources/migrations/</directory>
</resource>
</resources>
<plugins>
@ -334,8 +389,20 @@
<includes>
<include>net.sf.opencsv:opencsv</include>
<include>org.khelekore:prtree</include>
<include>org.flywaydb:flyway-core</include>
<include>com.sk89q:squirrelid</include>
</includes>
</artifactSet>
<relocations>
<relocation>
<pattern>org.flywaydb</pattern>
<shadedPattern>com.sk89q.worldguard.internal.flywaydb</shadedPattern>
</relocation>
<relocation>
<pattern>com.sk89q.squirrelid</pattern>
<shadedPattern>com.sk89q.worldguard.util.profile</shadedPattern>
</relocation>
</relocations>
</configuration>
</execution>
</executions>

View File

@ -35,4 +35,6 @@
<allow pkg="au.com.bytecode.opencsv"/>
<allow pkg="org.khelekore.prtree"/>
<allow pkg="com.google.common"/>
<allow pkg="com.jolbox.bonecp"/>
<allow pkg="org.flywaydb.core"/>
</import-control>

View File

@ -20,17 +20,30 @@
package com.sk89q.worldguard;
import com.sk89q.worldedit.Vector;
import com.sk89q.worldguard.domains.Association;
import com.sk89q.worldguard.protection.association.RegionAssociable;
import com.sk89q.worldguard.protection.regions.ProtectedRegion;
import java.util.UUID;
public abstract class LocalPlayer implements RegionAssociable {
public abstract class LocalPlayer {
/**
* Get a player's name.
* Get this player's name.
*
* @return The player's name
*/
public abstract String getName();
/**
* Get this player's unique ID.
*
* @return a UUID
*/
public abstract UUID getUniqueId();
/**
* Returns true if the player is inside a group.
* Returns true if this player is inside a group.
*
* @param group The group to check
* @return Whether this player is in {@code group}
@ -38,57 +51,67 @@ public abstract class LocalPlayer {
public abstract boolean hasGroup(String group);
/**
* Get the player's position.
* Get this player's position.
*
* @return The player's position
*/
public abstract Vector getPosition();
/**
* Kick the player.
* Kick this player.
*
* @param msg The message to kick the player with
*/
public abstract void kick(String msg);
/**
* Ban the player.
* Ban this player.
*
* @param msg The message to ban the player with
*/
public abstract void ban(String msg);
/**
* Send the player a message;
* Send this player a message.
*
* @param msg The message to send to the player
*/
public abstract void printRaw(String msg);
/**
* Get the player's list of groups.
* Get this player's list of groups.
*
* @return The groups this player is in
*/
public abstract String[] getGroups();
/**
* Returns whether a player has permission.
* Returns whether this player has permission.
*
* @param perm The permission to check
* @return Whether this player has {@code perm}
*/
public abstract boolean hasPermission(String perm);
@Override
public Association getAssociation(ProtectedRegion region) {
if (region.isOwner(this)) {
return Association.OWNER;
} else if (region.isMember(this)) {
return Association.MEMBER;
} else {
return Association.NON_MEMBER;
}
}
@Override
public boolean equals(Object obj) {
return obj instanceof LocalPlayer && ((LocalPlayer) obj).getName().equals(getName());
}
@Override
public int hashCode() {
return getName().hashCode();
}
}

View File

@ -39,16 +39,16 @@
import java.util.List;
import java.util.concurrent.TimeUnit;
import java.util.logging.Level;
import static com.google.common.base.Preconditions.checkNotNull;
import java.util.logging.Logger;
public abstract class Blacklist {
private static final Logger log = Logger.getLogger(Blacklist.class.getCanonicalName());
private MatcherIndex index = MatcherIndex.getEmptyInstance();
private final BlacklistLoggerHandler blacklistLogger = new BlacklistLoggerHandler();
private BlacklistEvent lastEvent;
private boolean useAsWhitelist;
private final java.util.logging.Logger logger;
private Cache<String, TrackedEvent> repeatingEventCache = CacheBuilder.newBuilder()
.maximumSize(1000)
.expireAfterAccess(30, TimeUnit.SECONDS)
@ -59,10 +59,8 @@ public TrackedEvent load(String s) throws Exception {
}
});
public Blacklist(boolean useAsWhitelist, java.util.logging.Logger logger) {
checkNotNull(logger);
public Blacklist(boolean useAsWhitelist) {
this.useAsWhitelist = useAsWhitelist;
this.logger = logger;
}
/**
@ -93,7 +91,7 @@ public boolean isWhitelist() {
}
/**
* Get the logger.
* Get the log.
*
* @return The logger used in this blacklist
*/
@ -165,14 +163,14 @@ public void load(File file) throws IOException {
builder.add(matcher, entry);
currentEntries.add(entry);
} catch (TargetMatcherParseException e) {
logger.log(Level.WARNING, "Could not parse a block/item heading: " + e.getMessage());
log.log(Level.WARNING, "Could not parse a block/item heading: " + e.getMessage());
}
}
} else if (currentEntries != null) {
String[] parts = line.split("=");
if (parts.length == 1) {
logger.log(Level.WARNING, "Found option with no value " + file.getName() + " for '" + line + "'");
log.log(Level.WARNING, "Found option with no value " + file.getName() + " for '" + line + "'");
continue;
}
@ -209,10 +207,10 @@ public void load(File file) throws IOException {
}
if (unknownOption) {
logger.log(Level.WARNING, "Unknown option '" + parts[0] + "' in " + file.getName() + " for '" + line + "'");
log.log(Level.WARNING, "Unknown option '" + parts[0] + "' in " + file.getName() + " for '" + line + "'");
}
} else {
logger.log(Level.WARNING, "Found option with no heading "
log.log(Level.WARNING, "Found option with no heading "
+ file.getName() + " for '" + line + "'");
}
}
@ -246,7 +244,7 @@ private List<Action> parseActions(BlacklistEntry entry, String raw) {
}
if (!found) {
logger.log(Level.WARNING, "Unknown blacklist action: " + name);
log.log(Level.WARNING, "Unknown blacklist action: " + name);
}
}

View File

@ -21,11 +21,14 @@
import com.sk89q.worldguard.blacklist.Blacklist;
public class BukkitBlacklist extends Blacklist {
import java.util.logging.Logger;
class BukkitBlacklist extends Blacklist {
private WorldGuardPlugin plugin;
public BukkitBlacklist(Boolean useAsWhitelist, WorldGuardPlugin plugin) {
super(useAsWhitelist, plugin.getLogger());
super(useAsWhitelist);
this.plugin = plugin;
}
@ -33,4 +36,5 @@ public BukkitBlacklist(Boolean useAsWhitelist, WorldGuardPlugin plugin) {
public void broadcastNotification(String msg) {
plugin.broadcastNotification(msg);
}
}

View File

@ -0,0 +1,78 @@
/*
* WorldGuard, a suite of tools for Minecraft
* Copyright (C) sk89q <http://www.sk89q.com>
* Copyright (C) WorldGuard team and contributors
*
* This program is free software: you can redistribute it and/or modify it
* under the terms of the GNU Lesser General Public License as published by the
* Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License
* for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package com.sk89q.worldguard.bukkit;
import com.sk89q.worldedit.Vector;
import com.sk89q.worldguard.LocalPlayer;
import org.bukkit.OfflinePlayer;
import java.util.UUID;
class BukkitOfflinePlayer extends LocalPlayer {
private final OfflinePlayer player;
BukkitOfflinePlayer(OfflinePlayer offlinePlayer) {
this.player = offlinePlayer;
}
@Override
public String getName() {
return player.getName();
}
@Override
public UUID getUniqueId() {
return player.getUniqueId();
}
@Override
public boolean hasGroup(String group) {
return false;
}
@Override
public Vector getPosition() {
return Vector.ZERO;
}
@Override
public void kick(String msg) {
}
@Override
public void ban(String msg) {
}
@Override
public void printRaw(String msg) {
}
@Override
public String[] getGroups() {
return new String[0];
}
@Override
public boolean hasPermission(String perm) {
return false;
}
}

View File

@ -25,18 +25,34 @@
import com.sk89q.worldedit.Vector;
import com.sk89q.worldguard.LocalPlayer;
import java.util.UUID;
import static com.google.common.base.Preconditions.checkNotNull;
public class BukkitPlayer extends LocalPlayer {
private Player player;
private WorldGuardPlugin plugin;
private final WorldGuardPlugin plugin;
private final Player player;
private final String name;
public BukkitPlayer(WorldGuardPlugin plugin, Player player) {
checkNotNull(plugin);
checkNotNull(player);
this.plugin = plugin;
this.player = player;
// getName() takes longer than before in newer versions of Minecraft
this.name = player.getName();
}
@Override
public String getName() {
return player.getName();
return name;
}
@Override
public UUID getUniqueId() {
return player.getUniqueId();
}
@Override
@ -75,4 +91,9 @@ public void printRaw(String msg) {
public boolean hasPermission(String perm) {
return plugin.hasPermission(player, perm);
}
public Player getPlayer() {
return player;
}
}

View File

@ -303,7 +303,7 @@ public static <T extends Enum<T>> T tryEnum(Class<T> enumType, String ... values
/**
* Get a blacklist target for the given block.
*
*
* @param block the block
* @return a target
*/
@ -312,6 +312,22 @@ public static Target createTarget(Block block) {
return new MaterialTarget(block.getTypeId(), block.getData());
}
/**
* Get a blacklist target for the given block.
*
* @param block the block
* @param material a fallback material
* @return a target
*/
public static Target createTarget(Block block, Material material) {
checkNotNull(material);
if (block.getType() == material) {
return new MaterialTarget(block.getTypeId(), block.getData());
} else {
return new MaterialTarget(material.getId(), (short) 0);
}
}
/**
* Get a blacklist target for the given item.
*

View File

@ -19,11 +19,17 @@
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.sql.SQLDriver;
import com.sk89q.worldguard.util.sql.DataSourceConfig;
import org.bukkit.World;
import org.bukkit.entity.Player;
@ -35,6 +41,7 @@
import java.util.Set;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.ConcurrentMap;
import java.util.logging.Logger;
/**
* Represents the global configuration and also delegates configuration
@ -45,6 +52,8 @@
*/
public class ConfigurationManager {
private static final Logger log = Logger.getLogger(ConfigurationManager.class.getCanonicalName());
private static final String CONFIG_HEADER = "#\r\n" +
"# WorldGuard's main configuration file\r\n" +
"#\r\n" +
@ -66,30 +75,11 @@ public class ConfigurationManager {
"# - Lines starting with # are comments and so they are ignored.\r\n" +
"#\r\n";
/**
* Reference to the plugin.
*/
private WorldGuardPlugin plugin;
/**
* Holds configurations for different worlds.
*/
private ConcurrentMap<String, WorldConfiguration> worlds;
/**
* The global configuration for use when loading worlds
*/
private YAMLProcessor config;
/**
* List of people with god mode.
*/
@Deprecated
private Set<String> hasGodMode = new HashSet<String>();
/**
* List of people who can breathe underwater.
*/
private Set<String> hasAmphibious = new HashSet<String>();
private boolean hasCommandBookGodMode = false;
@ -102,16 +92,15 @@ public class ConfigurationManager {
public boolean usePlayerTeleports;
public boolean deopOnJoin;
public boolean blockInGameOp;
public boolean migrateRegionsToUuid;
public boolean keepUnresolvedNames;
public Map<String, String> hostKeys = new HashMap<String, String>();
/**
* Region Storage Configuration method, and config values
*/
public boolean useSqlDatabase = false;
public String sqlDsn;
public String sqlUsername;
public String sqlPassword;
public String sqlTablePrefix;
public RegionDriver selectedRegionStoreDriver;
public Map<DriverType, RegionDriver> regionStoreDriverMap;
/**
* Construct the object.
@ -123,6 +112,25 @@ public ConfigurationManager(WorldGuardPlugin plugin) {
this.worlds = new ConcurrentHashMap<String, WorldConfiguration>();
}
/**
* Get the folder for storing data files and configuration.
*
* @return the data folder
*/
public File getDataFolder() {
return plugin.getDataFolder();
}
/**
* Get the folder for storing data files and configuration for each
* world.
*
* @return the data folder
*/
public File getWorldsDataFolder() {
return new File(getDataFolder(), "worlds");
}
/**
* Load the configuration.
*/
@ -136,12 +144,14 @@ public void load() {
try {
config.load();
} catch (IOException e) {
plugin.getLogger().severe("Error reading configuration for global config: ");
log.severe("Error reading configuration for global config: ");
e.printStackTrace();
}
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);
autoGodMode = config.getBoolean("auto-invincible", config.getBoolean("auto-invincible-permission", false));
config.removeProperty("auto-invincible-permission");
@ -163,13 +173,25 @@ public void load() {
}
}
useSqlDatabase = config.getBoolean(
"regions.sql.use", false);
// ====================================================================
// Region store drivers
// ====================================================================
sqlDsn = config.getString("regions.sql.dsn", "jdbc:mysql://localhost/worldguard");
sqlUsername = config.getString("regions.sql.username", "worldguard");
sqlPassword = config.getString("regions.sql.password", "worldguard");
sqlTablePrefix = config.getString("regions.sql.table-prefix", "");
boolean useSqlDatabase = config.getBoolean("regions.sql.use", false);
String sqlDsn = config.getString("regions.sql.dsn", "jdbc:mysql://localhost/worldguard");
String sqlUsername = config.getString("regions.sql.username", "worldguard");
String sqlPassword = config.getString("regions.sql.password", "worldguard");
String sqlTablePrefix = config.getString("regions.sql.table-prefix", "");
DataSourceConfig dataSourceConfig = new DataSourceConfig(sqlDsn, sqlUsername, sqlPassword, sqlTablePrefix);
SQLDriver sqlDriver = new SQLDriver(dataSourceConfig);
DirectoryYamlDriver yamlDriver = new DirectoryYamlDriver(getWorldsDataFolder(), "regions.yml");
this.regionStoreDriverMap = ImmutableMap.<DriverType, RegionDriver>builder()
.put(DriverType.MYSQL, sqlDriver)
.put(DriverType.YAML, yamlDriver)
.build();
this.selectedRegionStoreDriver = useSqlDatabase ? sqlDriver : yamlDriver;
// Load configurations for each world
for (World world : plugin.getServer().getWorlds()) {
@ -177,10 +199,6 @@ public void load() {
}
config.setHeader(CONFIG_HEADER);
if (!config.save()) {
plugin.getLogger().severe("Error saving configuration!");
}
}
/**
@ -190,6 +208,13 @@ public void unload() {
worlds.clear();
}
public void disableUuidMigration() {
config.setProperty("regions.uuid-migration.perform-on-next-start", false);
if (!config.save()) {
log.severe("Error saving configuration!");
}
}
/**
* Get the configuration for a world.
*

View File

@ -1,155 +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;
import com.sk89q.worldguard.protection.databases.CSVDatabase;
import com.sk89q.worldguard.protection.databases.ProtectionDatabaseException;
import com.sk89q.worldguard.protection.managers.RegionManager;
import org.bukkit.World;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
/**
* Utility methods for porting from legacy versions.
*/
public final class LegacyWorldGuardMigration {
private LegacyWorldGuardMigration() {
}
/**
* Port over the blacklist.
*
* @param plugin The plugin instance
*/
public static void migrateBlacklist(WorldGuardPlugin plugin) {
World mainWorld = plugin.getServer().getWorlds().get(0);
String mainWorldName = mainWorld.getName();
String newPath = "worlds/" + mainWorldName + "/blacklist.txt";
File oldFile = new File(plugin.getDataFolder(), "blacklist.txt");
File newFile = new File(plugin.getDataFolder(), newPath);
if (!newFile.exists() && oldFile.exists()) {
plugin.getLogger().warning("WorldGuard will now update your blacklist "
+ "from an older version of WorldGuard.");
// Need to make root directories
newFile.getParentFile().mkdirs();
if (copyFile(oldFile, newFile)) {
oldFile.renameTo(new File(plugin.getDataFolder(),
"blacklist.txt.old"));
} else {
plugin.getLogger().warning("blacklist.txt has been converted " +
"for the main world at " + newPath + "");
plugin.getLogger().warning("Your other worlds currently have no " +
"blacklist defined!");
}
}
}
/**
* Migrate region settings.
*
* @param plugin The plugin instance
*/
public static void migrateRegions(WorldGuardPlugin plugin) {
try {
File oldDatabase = new File(plugin.getDataFolder(), "regions.txt");
if (!oldDatabase.exists()) return;
plugin.getLogger().info("The regions database has changed in 5.x. "
+ "Your old regions database will be converted to the new format "
+ "and set as your primary world's database.");
World w = plugin.getServer().getWorlds().get(0);
RegionManager mgr = plugin.getGlobalRegionManager().get(w);
// First load up the old database using the CSV loader
CSVDatabase db = new CSVDatabase(oldDatabase, plugin.getLogger());
db.load();
// Then save the new database
mgr.setRegions(db.getRegions());
mgr.save();
oldDatabase.renameTo(new File(plugin.getDataFolder(), "regions.txt.old"));
plugin.getLogger().info("Regions database converted!");
} catch (ProtectionDatabaseException e) {
plugin.getLogger().warning("Failed to load regions: "
+ e.getMessage());
}
}
/**
* Copies a file.
*
* @param from The source file
* @param to The destination file
* @return true if successful
*/
private static boolean copyFile(File from, File to) {
InputStream in = null;
OutputStream out = null;
try {
in = new FileInputStream(from);
out = new FileOutputStream(to);
byte[] buf = new byte[1024];
int len;
while ((len = in.read(buf)) > 0) {
out.write(buf, 0, len);
}
in.close();
out.close();
return true;
} catch (FileNotFoundException ignore) {
} catch (IOException ignore) {
} finally {
if (in != null) {
try {
in.close();
} catch (IOException ignore) {
}
}
if (out != null) {
try {
out.close();
} catch (IOException ignore) {
}
}
}
return false;
}
}

View File

@ -0,0 +1,117 @@
/*
* WorldGuard, a suite of tools for Minecraft
* Copyright (C) sk89q <http://www.sk89q.com>
* Copyright (C) WorldGuard team and contributors
*
* This program is free software: you can redistribute it and/or modify it
* under the terms of the GNU Lesser General Public License as published by the
* Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License
* for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package com.sk89q.worldguard.bukkit;
import com.sk89q.worldguard.protection.ApplicableRegionSet;
import com.sk89q.worldguard.protection.RegionResultSet;
import com.sk89q.worldguard.protection.managers.RegionManager;
import org.bukkit.Location;
import org.bukkit.World;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.ConcurrentMap;
import static com.google.common.base.Preconditions.checkNotNull;
/**
* Keeps a cache of {@link RegionResultSet}s. The contents of the cache
* must be externally invalidated occasionally (and frequently).
*
* <p>This class is fully concurrent.</p>
*/
class QueryCache {
private final ConcurrentMap<CacheKey, ApplicableRegionSet> cache = new ConcurrentHashMap<CacheKey, ApplicableRegionSet>(16, 0.75f, 2);
/**
* Get from the cache a {@code ApplicableRegionSet} if an entry exists;
* otherwise, query the given manager for a result and cache it.
*
* @param manager the region manager
* @param location the location
* @return a result
*/
public ApplicableRegionSet queryContains(RegionManager manager, Location location) {
checkNotNull(manager);
checkNotNull(location);
CacheKey key = new CacheKey(location);
ApplicableRegionSet result = cache.get(key);
if (result == null) {
result = manager.getApplicableRegions(location);
cache.put(key, result);
}
return result;
}
/**
* Invalidate the cache and clear its contents.
*/
public void invalidateAll() {
cache.clear();
}
/**
* Key object for the map.
*/
private static class CacheKey {
private final World world;
private final int x;
private final int y;
private final int z;
private final int hashCode;
private CacheKey(Location location) {
this.world = location.getWorld();
this.x = location.getBlockX();
this.y = location.getBlockY();
this.z = location.getBlockZ();
// Pre-compute hash code
int result = world.hashCode();
result = 31 * result + x;
result = 31 * result + y;
result = 31 * result + z;
this.hashCode = result;
}
@Override
public boolean equals(Object o) {
if (this == o) return true;
if (o == null || getClass() != o.getClass()) return false;
CacheKey cacheKey = (CacheKey) o;
if (x != cacheKey.x) return false;
if (y != cacheKey.y) return false;
if (z != cacheKey.z) return false;
if (!world.equals(cacheKey.world)) return false;
return true;
}
@Override
public int hashCode() {
return hashCode;
}
}
}

View File

@ -0,0 +1,311 @@
/*
* WorldGuard, a suite of tools for Minecraft
* Copyright (C) sk89q <http://www.sk89q.com>
* Copyright (C) WorldGuard team and contributors
*
* This program is free software: you can redistribute it and/or modify it
* under the terms of the GNU Lesser General Public License as published by the
* Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License
* for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package com.sk89q.worldguard.bukkit;
import com.sk89q.worldedit.Vector2D;
import com.sk89q.worldguard.protection.managers.RegionContainerImpl;
import com.sk89q.worldguard.protection.managers.RegionManager;
import com.sk89q.worldguard.protection.managers.migration.Migration;
import com.sk89q.worldguard.protection.managers.migration.MigrationException;
import com.sk89q.worldguard.protection.managers.migration.UUIDMigration;
import com.sk89q.worldguard.protection.managers.storage.RegionDriver;
import org.bukkit.Bukkit;
import org.bukkit.Chunk;
import org.bukkit.World;
import org.bukkit.event.EventHandler;
import org.bukkit.event.Listener;
import org.bukkit.event.world.ChunkLoadEvent;
import org.bukkit.event.world.ChunkUnloadEvent;
import org.bukkit.event.world.WorldLoadEvent;
import org.bukkit.event.world.WorldUnloadEvent;
import javax.annotation.Nullable;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.Set;
import java.util.logging.Level;
import java.util.logging.Logger;
import static com.google.common.base.Preconditions.checkNotNull;
/**
* A region container creates {@link RegionManager}s for loaded worlds, which
* allows access to the region data of a world. Generally, only data is
* loaded for worlds that are loaded in the server.
*
* <p>This class is thread safe and its contents can be accessed from
* multiple concurrent threads.</p>
*
* <p>An instance of this class can be retrieved using
* {@link WorldGuardPlugin#getRegionContainer()}.</p>
*/
public class RegionContainer {
private static final Logger log = Logger.getLogger(RegionContainer.class.getCanonicalName());
/**
* Invalidation frequency in ticks.
*/
private static final int CACHE_INVALIDATION_INTERVAL = 2;
private final Object lock = new Object();
private final WorldGuardPlugin plugin;
private final QueryCache cache = new QueryCache();
private RegionContainerImpl container;
/**
* Create a new instance.
*
* @param plugin the plugin
*/
RegionContainer(WorldGuardPlugin plugin) {
this.plugin = plugin;
}
/**
* Initialize the region container.
*/
void initialize() {
ConfigurationManager config = plugin.getGlobalStateManager();
container = new RegionContainerImpl(config.selectedRegionStoreDriver);
// Migrate to UUIDs
autoMigrate();
loadWorlds();
Bukkit.getPluginManager().registerEvents(new Listener() {
@EventHandler
public void onWorldLoad(WorldLoadEvent event) {
load(event.getWorld());
}
@EventHandler
public void onWorldUnload(WorldUnloadEvent event) {
unload(event.getWorld());
}
@EventHandler
public void onChunkLoad(ChunkLoadEvent event) {
RegionManager manager = get(event.getWorld());
if (manager != null) {
Chunk chunk = event.getChunk();
manager.loadChunk(new Vector2D(chunk.getX(), chunk.getZ()));
}
}
@EventHandler
public void onChunkUnload(ChunkUnloadEvent event) {
RegionManager manager = get(event.getWorld());
if (manager != null) {
Chunk chunk = event.getChunk();
manager.unloadChunk(new Vector2D(chunk.getX(), chunk.getZ()));
}
}
}, plugin);
Bukkit.getScheduler().scheduleSyncRepeatingTask(plugin, new Runnable() {
@Override
public void run() {
cache.invalidateAll();
}
}, CACHE_INVALIDATION_INTERVAL, CACHE_INVALIDATION_INTERVAL);
}
/**
* Save data and unload.
*/
void unload() {
synchronized (lock) {
container.unloadAll();
}
}
/**
* Get the region store driver.
*
* @return the driver
*/
public RegionDriver getDriver() {
return container.getDriver();
}
/**
* Try loading the region managers for all currently loaded worlds.
*/
private void loadWorlds() {
synchronized (lock) {
for (World world : Bukkit.getServer().getWorlds()) {
load(world);
}
}
}
/**
* Reload the region container.
*
* <p>This method may block until the data for all loaded worlds has been
* unloaded and new data has been loaded.</p>
*/
public void reload() {
synchronized (lock) {
unload();
loadWorlds();
}
}
/**
* Load the region data for a world if it has not been loaded already.
*
* @param world the world
* @return a region manager, either returned from the cache or newly loaded
*/
@Nullable
private RegionManager load(World world) {
checkNotNull(world);
WorldConfiguration config = plugin.getGlobalStateManager().get(world);
if (!config.useRegions) {
return null;
}
RegionManager manager;
synchronized (lock) {
manager = container.load(world.getName());
if (manager != null) {
// Bias the region data for loaded chunks
List<Vector2D> positions = new ArrayList<Vector2D>();
for (Chunk chunk : world.getLoadedChunks()) {
positions.add(new Vector2D(chunk.getX(), chunk.getZ()));
}
manager.loadChunks(positions);
}
}
return manager;
}
/**
* Unload the region data for a world.
*
* @param world a world
*/
void unload(World world) {
checkNotNull(world);
synchronized (lock) {
container.unload(world.getName());
}
}
/**
* Get the region manager for a world if one exists.
*
* <p>If you wish to make queries and performance is more important
* than accuracy, use {@link #createQuery()} instead.</p>
*
* <p>This method may return {@code null} if region data for the given
* world has not been loaded, has failed to load, or support for regions
* has been disabled.</p>
*
* @param world the world
* @return a region manager, or {@code null} if one is not available
*/
@Nullable
public RegionManager get(World world) {
return container.get(world.getName());
}
/**
* Get an immutable list of loaded {@link RegionManager}s.
*
* @return a list of managers
*/
public List<RegionManager> getLoaded() {
return Collections.unmodifiableList(container.getLoaded());
}
/**
* Get the a set of region managers that are failing to save.
*
* @return a set of region managers
*/
public Set<RegionManager> getSaveFailures() {
return container.getSaveFailures();
}
/**
* Create a new region query.
*
* @return a new query
*/
public RegionQuery createQuery() {
return new RegionQuery(plugin, cache);
}
/**
* Execute a migration and block any loading of region data during
* the migration.
*
* @param migration the migration
* @throws MigrationException thrown by the migration on error
*/
public void migrate(Migration migration) throws MigrationException {
checkNotNull(migration);
synchronized (lock) {
try {
log.info("Unloading and saving region data that is currently loaded...");
unload();
migration.migrate();
} finally {
log.info("Loading region data for loaded worlds...");
loadWorlds();
}
}
}
/**
* Execute auto-migration.
*/
private void autoMigrate() {
ConfigurationManager config = plugin.getGlobalStateManager();
if (config.migrateRegionsToUuid) {
RegionDriver driver = getDriver();
UUIDMigration migrator = new UUIDMigration(driver, plugin.getProfileService());
migrator.setKeepUnresolvedNames(config.keepUnresolvedNames);
try {
migrate(migrator);
log.info("Regions saved after UUID migration! This won't happen again unless " +
"you change the relevant configuration option in WorldGuard's config.");
config.disableUuidMigration();
} catch (MigrationException e) {
log.log(Level.WARNING, "Failed to execute the migration", e);
}
}
}
}

View File

@ -0,0 +1,260 @@
/*
* WorldGuard, a suite of tools for Minecraft
* Copyright (C) sk89q <http://www.sk89q.com>
* Copyright (C) WorldGuard team and contributors
*
* This program is free software: you can redistribute it and/or modify it
* under the terms of the GNU Lesser General Public License as published by the
* Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License
* for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package com.sk89q.worldguard.bukkit;
import com.sk89q.worldguard.LocalPlayer;
import com.sk89q.worldguard.protection.ApplicableRegionSet;
import com.sk89q.worldguard.protection.FailedLoadRegionSet;
import com.sk89q.worldguard.protection.GlobalRegionManager;
import com.sk89q.worldguard.protection.PermissiveRegionSet;
import com.sk89q.worldguard.protection.RegionResultSet;
import com.sk89q.worldguard.protection.association.RegionAssociable;
import com.sk89q.worldguard.protection.flags.DefaultFlag;
import com.sk89q.worldguard.protection.flags.Flag;
import com.sk89q.worldguard.protection.flags.StateFlag;
import com.sk89q.worldguard.protection.flags.StateFlag.State;
import com.sk89q.worldguard.protection.managers.RegionManager;
import org.bukkit.Location;
import org.bukkit.World;
import org.bukkit.entity.Player;
import javax.annotation.Nullable;
import java.util.Collection;
import static com.google.common.base.Preconditions.checkNotNull;
/**
* This object allows easy spatial queries involving region data for the
* purpose of implementing protection / region flag checks.
*
* <p>Results may be cached for brief amounts of time. If you want to get
* data for the purposes of changing it, use of this class is not recommended.
* Some of the return values of the methods may be simulated to reduce
* boilerplate code related to implementing protection, meaning that false
* data is returned.</p>
*/
public class RegionQuery {
private final WorldGuardPlugin plugin;
private final ConfigurationManager config;
@SuppressWarnings("deprecation")
private final GlobalRegionManager globalManager;
private final QueryCache cache;
/**
* Create a new instance.
*
* @param plugin the plugin
* @param cache the query cache
*/
RegionQuery(WorldGuardPlugin plugin, QueryCache cache) {
checkNotNull(plugin);
checkNotNull(cache);
this.plugin = plugin;
this.config = plugin.getGlobalStateManager();
this.cache = cache;
//noinspection deprecation
this.globalManager = plugin.getGlobalRegionManager();
}
/**
* Query for regions containing the given location.
*
* <p>An instance of {@link RegionResultSet} will always be returned,
* even if regions are disabled or region data failed to load. An
* appropriate "virtual" set will be returned in such a case
* (for example, if regions are disabled, the returned set
* would permit all activities).</p>
*
* @param location the location
* @return a region set
*/
public ApplicableRegionSet getApplicableRegions(Location location) {
checkNotNull(location);
World world = location.getWorld();
WorldConfiguration worldConfig = config.get(world);
if (!worldConfig.useRegions) {
return PermissiveRegionSet.getInstance();
}
RegionManager manager = globalManager.get(location.getWorld());
if (manager != null) {
return cache.queryContains(manager, location);
} else {
return FailedLoadRegionSet.getInstance();
}
}
/**
* Test whether the given flags evaluate to {@code ALLOW}, implicitly also
* considering the {@link DefaultFlag#BUILD} flag.
*
* <p>This method is equivalent to calling
* {@link #testState(Location, Player, StateFlag...)} with
* {@code flags} plus the {@code BUILD} flag.</p>
*
* <p>This method does not check the region bypass permission. That must
* be done by the calling code.</p>
*
* @param location the location
* @param player the player
* @param flags zero or more flags
* @return true if permission is granted
* @see RegionResultSet#testBuild(RegionAssociable, StateFlag...)
*/
public boolean testBuild(Location location, Player player, StateFlag... flags) {
checkNotNull(location);
checkNotNull(player);
LocalPlayer localPlayer = plugin.wrapPlayer(player);
return testBuild(location, localPlayer, flags);
}
/**
* Test whether the given flags evaluate to {@code ALLOW}, implicitly also
* considering the {@link DefaultFlag#BUILD} flag.
*
* <p>This method is equivalent to calling
* {@link #testState(Location, Player, StateFlag...)} with
* {@code flags} plus the {@code BUILD} flag.</p>
*
* <p>This method does not check the region bypass permission. That must
* be done by the calling code.</p>
*
* @param location the location
* @param subject the subject
* @param flags zero or more flags
* @return true if permission is granted
* @see RegionResultSet#testBuild(RegionAssociable, StateFlag...)
*/
public boolean testBuild(Location location, RegionAssociable subject, StateFlag... flags) {
checkNotNull(location);
checkNotNull(subject);
checkNotNull(flags);
World world = location.getWorld();
WorldConfiguration worldConfig = config.get(world);
return !worldConfig.useRegions || getApplicableRegions(location).testBuild(subject, flags);
}
/**
* Test whether the (effective) value for a list of state flags equals
* {@code ALLOW}.
*
* <p>{@code player} can be non-null to satisfy region group requirements,
* otherwise it will be assumed that the caller that is not a member of any
* regions. (Flags on a region can be changed so that they only apply
* to certain users.) The player argument is required if the
* {@link DefaultFlag#BUILD} flag is in the list of flags.</p>
*
* <p>This method does not check the region bypass permission. That must
* be done by the calling code.</p>
*
* @param location the location
* @param player an optional player, which would be used to determine the region group to apply
* @param flag the flag
* @return true if the result was {@code ALLOW}
* @see RegionResultSet#queryValue(RegionAssociable, Flag)
*/
public boolean testState(Location location, @Nullable Player player, StateFlag... flag) {
return StateFlag.test(queryState(location, player, flag));
}
/**
* Get the (effective) value for a list of state flags. The rules of
* states is observed here; that is, {@code DENY} overrides {@code ALLOW},
* and {@code ALLOW} overrides {@code NONE}. One flag may override another.
*
* <p>{@code player} can be non-null to satisfy region group requirements,
* otherwise it will be assumed that the caller that is not a member of any
* regions. (Flags on a region can be changed so that they only apply
* to certain users.) The player argument is required if the
* {@link DefaultFlag#BUILD} flag is in the list of flags.</p>
*
* @param location the location
* @param player an optional player, which would be used to determine the region groups that apply
* @param flags a list of flags to check
* @return a state
* @see RegionResultSet#queryState(RegionAssociable, StateFlag...)
*/
@Nullable
public State queryState(Location location, @Nullable Player player, StateFlag... flags) {
LocalPlayer localPlayer = player != null ? plugin.wrapPlayer(player) : null;
return getApplicableRegions(location).queryState(localPlayer, flags);
}
/**
* Get the effective value for a flag. If there are multiple values
* (for example, multiple overlapping regions with
* the same priority may have the same flag set), then the selected
* (or "winning") value will depend on the flag type.
*
* <p>Only some flag types actually have a strategy for picking the
* "best value." For most types, the actual value that is chosen to be
* returned is undefined (it could be any value). As of writing, the only
* type of flag that actually has a strategy for picking a value is the
* {@link StateFlag}.</p>
*
* <p>{@code player} can be non-null to satisfy region group requirements,
* otherwise it will be assumed that the caller that is not a member of any
* regions. (Flags on a region can be changed so that they only apply
* to certain users.) The player argument is required if the
* {@link DefaultFlag#BUILD} flag is the flag being queried.</p>
*
* @param location the location
* @param player an optional player, which would be used to determine the region group to apply
* @param flag the flag
* @return a value, which could be {@code null}
* @see RegionResultSet#queryValue(RegionAssociable, Flag)
*/
@Nullable
public <V> V queryValue(Location location, @Nullable Player player, Flag<V> flag) {
LocalPlayer localPlayer = player != null ? plugin.wrapPlayer(player) : null;
return getApplicableRegions(location).queryValue(localPlayer, flag);
}
/**
* Get the effective values for a flag, returning a collection of all
* values. It is up to the caller to determine which value, if any,
* from the collection will be used.
*
* <p>{@code player} can be non-null to satisfy region group requirements,
* otherwise it will be assumed that the caller that is not a member of any
* regions. (Flags on a region can be changed so that they only apply
* to certain users.) The player argument is required if the
* {@link DefaultFlag#BUILD} flag is the flag being queried.</p>
*
* @param location the location
* @param player an optional player, which would be used to determine the region group to apply
* @param flag the flag
* @return a collection of values
* @see RegionResultSet#queryAllValues(RegionAssociable, Flag)
*/
public <V> Collection<V> queryAllValues(Location location, @Nullable Player player, Flag<V> flag) {
LocalPlayer localPlayer = player != null ? plugin.wrapPlayer(player) : null;
return getApplicableRegions(location).queryAllValues(localPlayer, flag);
}
}

View File

@ -43,6 +43,7 @@
import java.util.Map;
import java.util.Set;
import java.util.logging.Level;
import java.util.logging.Logger;
/**
* Holds the configuration for individual worlds.
@ -52,6 +53,8 @@
*/
public class WorldConfiguration {
private static final Logger log = Logger.getLogger(WorldConfiguration.class.getCanonicalName());
public static final String CONFIG_HEADER = "#\r\n" +
"# WorldGuard's world configuration file\r\n" +
"#\r\n" +
@ -127,6 +130,7 @@ public class WorldConfiguration {
public boolean disableMobDamage;
public boolean useRegions;
public boolean highFreqFlags;
public boolean checkLiquidFlow;
public int regionWand;
public Set<EntityType> blockCreatureSpawn;
public boolean allowTamedSpawns;
@ -165,6 +169,7 @@ public class WorldConfiguration {
public boolean disableSoilDehydration;
public Set<Integer> allowedSnowFallOver;
public boolean regionInvinciblityRemovesMobs;
public boolean fakePlayerBuildOverride;
public boolean explosionFlagCancellation;
public boolean disableDeathMessages;
public boolean disableObsidianGenerators;
@ -197,7 +202,7 @@ public WorldConfiguration(WorldGuardPlugin plugin, String worldName, YAMLProcess
loadConfiguration();
if (summaryOnStart) {
plugin.getLogger().info("Loaded configuration for world '" + worldName + "'");
log.info("Loaded configuration for world '" + worldName + "'");
}
}
@ -300,7 +305,7 @@ private void loadConfiguration() {
try {
config.load();
} catch (IOException e) {
plugin.getLogger().severe("Error reading configuration for world " + worldName + ": ");
log.severe("Error reading configuration for world " + worldName + ": ");
e.printStackTrace();
}
@ -317,7 +322,7 @@ private void loadConfiguration() {
PotionEffectType effect = PotionEffectType.getByName(potionName);
if (effect == null) {
plugin.getLogger().warning("Unknown potion effect type '" + potionName + "'");
log.warning("Unknown potion effect type '" + potionName + "'");
} else {
blockPotions.add(effect);
}
@ -410,8 +415,10 @@ private void loadConfiguration() {
useRegions = getBoolean("regions.enable", true);
regionInvinciblityRemovesMobs = getBoolean("regions.invincibility-removes-mobs", false);
fakePlayerBuildOverride = getBoolean("regions.fake-player-build-override", true);
explosionFlagCancellation = getBoolean("regions.explosion-flags-block-entity-damage", true);
highFreqFlags = getBoolean("regions.high-frequency-flags", false);
checkLiquidFlow = getBoolean("regions.protect-against-liquid-flow", false);
regionWand = getInt("regions.wand", 334);
maxClaimVolume = getInt("regions.max-claim-volume", 30000);
claimOnlyInsideExistingRegions = getBoolean("regions.claim-only-inside-existing-regions", false);
@ -438,9 +445,9 @@ private void loadConfiguration() {
EntityType creature = EntityType.fromName(creatureName);
if (creature == null) {
plugin.getLogger().warning("Unknown mob type '" + creatureName + "'");
log.warning("Unknown mob type '" + creatureName + "'");
} else if (!creature.isAlive()) {
plugin.getLogger().warning("Entity type '" + creatureName + "' is not a creature");
log.warning("Entity type '" + creatureName + "' is not a creature");
} else {
blockCreatureSpawn.add(creature);
}
@ -481,53 +488,53 @@ private void loadConfiguration() {
} else {
this.blacklist = blist;
if (summaryOnStart) {
plugin.getLogger().log(Level.INFO, "Blacklist loaded.");
log.log(Level.INFO, "Blacklist loaded.");
}
BlacklistLoggerHandler blacklistLogger = blist.getLogger();
if (logDatabase) {
blacklistLogger.addHandler(new DatabaseHandler(dsn, user, pass, table, worldName, plugin.getLogger()));
blacklistLogger.addHandler(new DatabaseHandler(dsn, user, pass, table, worldName, log));
}
if (logConsole) {
blacklistLogger.addHandler(new ConsoleHandler(worldName, plugin.getLogger()));
blacklistLogger.addHandler(new ConsoleHandler(worldName, log));
}
if (logFile) {
FileHandler handler =
new FileHandler(logFilePattern, logFileCacheSize, worldName, plugin.getLogger());
new FileHandler(logFilePattern, logFileCacheSize, worldName, log);
blacklistLogger.addHandler(handler);
}
}
} catch (FileNotFoundException e) {
plugin.getLogger().log(Level.WARNING, "WorldGuard blacklist does not exist.");
log.log(Level.WARNING, "WorldGuard blacklist does not exist.");
} catch (IOException e) {
plugin.getLogger().log(Level.WARNING, "Could not load WorldGuard blacklist: "
log.log(Level.WARNING, "Could not load WorldGuard blacklist: "
+ e.getMessage());
}
// Print an overview of settings
if (summaryOnStart) {
plugin.getLogger().log(Level.INFO, blockTNTExplosions
log.log(Level.INFO, blockTNTExplosions
? "(" + worldName + ") TNT ignition is blocked."
: "(" + worldName + ") TNT ignition is PERMITTED.");
plugin.getLogger().log(Level.INFO, blockLighter
log.log(Level.INFO, blockLighter
? "(" + worldName + ") Lighters are blocked."
: "(" + worldName + ") Lighters are PERMITTED.");
plugin.getLogger().log(Level.INFO, preventLavaFire
log.log(Level.INFO, preventLavaFire
? "(" + worldName + ") Lava fire is blocked."
: "(" + worldName + ") Lava fire is PERMITTED.");
if (disableFireSpread) {
plugin.getLogger().log(Level.INFO, "(" + worldName + ") All fire spread is disabled.");
log.log(Level.INFO, "(" + worldName + ") All fire spread is disabled.");
} else {
if (disableFireSpreadBlocks.size() > 0) {
plugin.getLogger().log(Level.INFO, "(" + worldName
log.log(Level.INFO, "(" + worldName
+ ") Fire spread is limited to "
+ disableFireSpreadBlocks.size() + " block types.");
} else {
plugin.getLogger().log(Level.INFO, "(" + worldName
log.log(Level.INFO, "(" + worldName
+ ") Fire spread is UNRESTRICTED.");
}
}

View File

@ -1,216 +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;
import com.sk89q.worldedit.blocks.ItemID;
import com.sk89q.worldguard.blacklist.event.BlockBreakBlacklistEvent;
import com.sk89q.worldguard.blacklist.event.ItemUseBlacklistEvent;
import com.sk89q.worldguard.blacklist.target.MaterialTarget;
import com.sk89q.worldguard.protection.flags.DefaultFlag;
import org.bukkit.ChatColor;
import org.bukkit.World;
import org.bukkit.block.Block;
import org.bukkit.entity.Creeper;
import org.bukkit.entity.Entity;
import org.bukkit.entity.Hanging;
import org.bukkit.entity.ItemFrame;
import org.bukkit.entity.LivingEntity;
import org.bukkit.entity.Painting;
import org.bukkit.entity.Player;
import org.bukkit.entity.Projectile;
import org.bukkit.event.EventHandler;
import org.bukkit.event.EventPriority;
import org.bukkit.event.Listener;
import org.bukkit.event.hanging.HangingBreakByEntityEvent;
import org.bukkit.event.hanging.HangingBreakEvent;
import org.bukkit.event.hanging.HangingBreakEvent.RemoveCause;
import org.bukkit.event.hanging.HangingPlaceEvent;
import org.bukkit.event.player.PlayerInteractEntityEvent;
import org.bukkit.projectiles.ProjectileSource;
import static com.sk89q.worldguard.bukkit.BukkitUtil.toVector;
/**
* Listener for painting related events.
*
* @author BangL <henno.rickowski@gmail.com>
*/
public class WorldGuardHangingListener implements Listener {
private WorldGuardPlugin plugin;
/**
* Construct the object;
*
* @param plugin The plugin instance
*/
public WorldGuardHangingListener(WorldGuardPlugin plugin) {
this.plugin = plugin;
}
/**
* Register events.
*/
public void registerEvents() {
plugin.getServer().getPluginManager().registerEvents(this, plugin);
}
@EventHandler(priority = EventPriority.HIGH, ignoreCancelled = true)
public void onHangingingBreak(HangingBreakEvent event) {
Hanging hanging = event.getEntity();
World world = hanging.getWorld();
ConfigurationManager cfg = plugin.getGlobalStateManager();
WorldConfiguration wcfg = cfg.get(world);
if (event instanceof HangingBreakByEntityEvent) {
HangingBreakByEntityEvent entityEvent = (HangingBreakByEntityEvent) event;
Entity removerEntity = entityEvent.getRemover();
if (removerEntity instanceof Projectile) {
Projectile projectile = (Projectile) removerEntity;
ProjectileSource remover = projectile.getShooter();
removerEntity = (remover instanceof LivingEntity ? (LivingEntity) remover : null);
}
if (removerEntity instanceof Player) {
Player player = (Player) removerEntity;
if (wcfg.getBlacklist() != null) {
if (hanging instanceof Painting
&& !wcfg.getBlacklist().check(
new BlockBreakBlacklistEvent(plugin.wrapPlayer(player),
toVector(player.getLocation()), new MaterialTarget(ItemID.PAINTING, (short) 0)), false, false)) {
event.setCancelled(true);
return;
} else if (hanging instanceof ItemFrame
&& !wcfg.getBlacklist().check(
new BlockBreakBlacklistEvent(plugin.wrapPlayer(player),
toVector(player.getLocation()), new MaterialTarget(ItemID.ITEM_FRAME, (short) 0)), false, false)) {
event.setCancelled(true);
return;
}
}
if (wcfg.useRegions) {
if (!plugin.getGlobalRegionManager().canBuild(player, hanging.getLocation())) {
player.sendMessage(ChatColor.DARK_RED + "You don't have permission for this area.");
event.setCancelled(true);
return;
}
}
} else {
if (removerEntity instanceof Creeper) {
if (wcfg.blockCreeperBlockDamage || wcfg.blockCreeperExplosions) {
event.setCancelled(true);
return;
}
if (wcfg.useRegions && !plugin.getGlobalRegionManager().allows(DefaultFlag.CREEPER_EXPLOSION, hanging.getLocation())) {
event.setCancelled(true);
return;
}
}
// this now covers dispensers as well, if removerEntity is null above,
// due to a non-LivingEntity ProjectileSource
if (hanging instanceof Painting
&& (wcfg.blockEntityPaintingDestroy
|| (wcfg.useRegions
&& !plugin.getGlobalRegionManager().allows(DefaultFlag.ENTITY_PAINTING_DESTROY, hanging.getLocation())))) {
event.setCancelled(true);
} else if (hanging instanceof ItemFrame
&& (wcfg.blockEntityItemFrameDestroy
|| (wcfg.useRegions
&& !plugin.getGlobalRegionManager().allows(DefaultFlag.ENTITY_ITEM_FRAME_DESTROY, hanging.getLocation())))) {
event.setCancelled(true);
}
}
} else {
// Explosions from mobs are not covered by HangingBreakByEntity
if (hanging instanceof Painting && wcfg.blockEntityPaintingDestroy
&& event.getCause() == RemoveCause.EXPLOSION) {
event.setCancelled(true);
} else if (hanging instanceof ItemFrame && wcfg.blockEntityItemFrameDestroy
&& event.getCause() == RemoveCause.EXPLOSION) {
event.setCancelled(true);
}
}
}
@EventHandler(priority = EventPriority.HIGH, ignoreCancelled = true)
public void onHangingPlace(HangingPlaceEvent event) {
Block placedOn = event.getBlock();
Player player = event.getPlayer();
World world = placedOn.getWorld();
ConfigurationManager cfg = plugin.getGlobalStateManager();
WorldConfiguration wcfg = cfg.get(world);
if (wcfg.getBlacklist() != null) {
if (event.getEntity() instanceof Painting
&& !wcfg.getBlacklist().check(
new ItemUseBlacklistEvent(plugin.wrapPlayer(player),
toVector(player.getLocation()), new MaterialTarget(ItemID.PAINTING, (short) 0)), false, false)) {
event.setCancelled(true);
return;
} else if (event.getEntity() instanceof ItemFrame
&& !wcfg.getBlacklist().check(
new ItemUseBlacklistEvent(plugin.wrapPlayer(player),
toVector(player.getLocation()), new MaterialTarget(ItemID.ITEM_FRAME, (short) 0)), false, false)) {
event.setCancelled(true);
return;
}
}
if (wcfg.useRegions) {
if (!plugin.getGlobalRegionManager().canBuild(player, placedOn.getRelative(event.getBlockFace()))) {
player.sendMessage(ChatColor.DARK_RED + "You don't have permission for this area.");
event.setCancelled(true);
return;
}
}
}
@EventHandler(priority = EventPriority.HIGH, ignoreCancelled = true)
public void onEntityInteract(PlayerInteractEntityEvent event) {
Player player = event.getPlayer();
Entity entity = event.getRightClicked();
ConfigurationManager cfg = plugin.getGlobalStateManager();
WorldConfiguration wcfg = cfg.get(entity.getWorld());
if (wcfg.useRegions && (entity instanceof ItemFrame || entity instanceof Painting)) {
if (!plugin.getGlobalRegionManager().canBuild(player, entity.getLocation())) {
player.sendMessage(ChatColor.DARK_RED + "You don't have permission for this area.");
event.setCancelled(true);
return;
}
// if (entity instanceof ItemFrame
// && ((!plugin.getGlobalRegionManager().allows(
// DefaultFlag.ENTITY_ITEM_FRAME_DESTROY, entity.getLocation())))) {
// event.setCancelled(true);
// } else if (entity instanceof Painting
// && ((!plugin.getGlobalRegionManager().allows(
// DefaultFlag.ENTITY_PAINTING_DESTROY, entity.getLocation())))) {
// event.setCancelled(true);
// }
}
}
}

View File

@ -19,6 +19,9 @@
package com.sk89q.worldguard.bukkit;
import com.google.common.util.concurrent.Futures;
import com.google.common.util.concurrent.ListeningExecutorService;
import com.google.common.util.concurrent.MoreExecutors;
import com.sk89q.bukkit.util.CommandsManagerRegistration;
import com.sk89q.minecraft.util.commands.CommandException;
import com.sk89q.minecraft.util.commands.CommandPermissionsException;
@ -27,21 +30,50 @@
import com.sk89q.minecraft.util.commands.MissingNestedCommandException;
import com.sk89q.minecraft.util.commands.SimpleInjector;
import com.sk89q.minecraft.util.commands.WrappedCommandException;
import com.sk89q.squirrelid.cache.HashMapCache;
import com.sk89q.squirrelid.cache.ProfileCache;
import com.sk89q.squirrelid.cache.SQLiteCache;
import com.sk89q.squirrelid.resolver.BukkitPlayerService;
import com.sk89q.squirrelid.resolver.CacheForwardingService;
import com.sk89q.squirrelid.resolver.CombinedProfileService;
import com.sk89q.squirrelid.resolver.HttpRepositoryService;
import com.sk89q.squirrelid.resolver.ProfileService;
import com.sk89q.wepif.PermissionsResolverManager;
import com.sk89q.worldedit.bukkit.WorldEditPlugin;
import com.sk89q.worldguard.LocalPlayer;
import com.sk89q.worldguard.bukkit.commands.GeneralCommands;
import com.sk89q.worldguard.bukkit.commands.ProtectionCommands;
import com.sk89q.worldguard.bukkit.commands.ToggleCommands;
import com.sk89q.worldguard.internal.listener.BlacklistListener;
import com.sk89q.worldguard.internal.listener.BlockedPotionsListener;
import com.sk89q.worldguard.internal.listener.ChestProtectionListener;
import com.sk89q.worldguard.internal.listener.RegionProtectionListener;
import com.sk89q.worldguard.bukkit.listener.BlacklistListener;
import com.sk89q.worldguard.bukkit.listener.BlockedPotionsListener;
import com.sk89q.worldguard.bukkit.listener.ChestProtectionListener;
import com.sk89q.worldguard.bukkit.listener.DebuggingListener;
import com.sk89q.worldguard.bukkit.listener.EventAbstractionListener;
import com.sk89q.worldguard.bukkit.listener.FlagStateManager;
import com.sk89q.worldguard.bukkit.listener.RegionFlagsListener;
import com.sk89q.worldguard.bukkit.listener.RegionProtectionListener;
import com.sk89q.worldguard.bukkit.listener.WorldGuardBlockListener;
import com.sk89q.worldguard.bukkit.listener.WorldGuardCommandBookListener;
import com.sk89q.worldguard.bukkit.listener.WorldGuardEntityListener;
import com.sk89q.worldguard.bukkit.listener.WorldGuardHangingListener;
import com.sk89q.worldguard.bukkit.listener.WorldGuardPlayerListener;
import com.sk89q.worldguard.bukkit.listener.WorldGuardServerListener;
import com.sk89q.worldguard.bukkit.listener.WorldGuardVehicleListener;
import com.sk89q.worldguard.bukkit.listener.WorldGuardWeatherListener;
import com.sk89q.worldguard.bukkit.listener.WorldGuardWorldListener;
import com.sk89q.worldguard.protection.GlobalRegionManager;
import com.sk89q.worldguard.protection.managers.RegionManager;
import com.sk89q.worldguard.protection.managers.storage.StorageException;
import com.sk89q.worldguard.protection.util.UnresolvedNamesException;
import com.sk89q.worldguard.util.FatalConfigurationLoadingException;
import com.sk89q.worldguard.util.concurrent.EvenMoreExecutors;
import com.sk89q.worldguard.util.logging.RecordMessagePrefixer;
import com.sk89q.worldguard.util.task.SimpleSupervisor;
import com.sk89q.worldguard.util.task.Supervisor;
import com.sk89q.worldguard.util.task.Task;
import org.bukkit.ChatColor;
import org.bukkit.Location;
import org.bukkit.OfflinePlayer;
import org.bukkit.World;
import org.bukkit.World.Environment;
import org.bukkit.block.Block;
@ -53,6 +85,7 @@
import org.bukkit.plugin.Plugin;
import org.bukkit.plugin.java.JavaPlugin;
import javax.annotation.Nullable;
import java.io.File;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
@ -63,51 +96,38 @@
import java.util.Iterator;
import java.util.List;
import java.util.Set;
import java.util.concurrent.CancellationException;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.RejectedExecutionException;
import java.util.concurrent.TimeUnit;
import java.util.jar.JarFile;
import java.util.logging.Level;
import java.util.logging.Logger;
import java.util.zip.ZipEntry;
/**
* The main class for WorldGuard as a Bukkit plugin.
*
* @author sk89q
*/
public class WorldGuardPlugin extends JavaPlugin {
/**
* Current instance of this plugin.
*/
private static final Logger log = Logger.getLogger(WorldGuardPlugin.class.getCanonicalName());
private static WorldGuardPlugin inst;
/**
* Manager for commands. This automatically handles nested commands,
* permissions checking, and a number of other fancy command things.
* We just set it up and register commands against it.
*/
private final CommandsManager<CommandSender> commands;
/**
* Handles the region databases for all worlds.
*/
private final GlobalRegionManager globalRegionManager;
/**
* Handles all configuration.
*/
private final ConfigurationManager configuration;
/**
* Used for scheduling flags.
*/
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 final Supervisor supervisor = new SimpleSupervisor();
private ListeningExecutorService executorService;
private ProfileService profileService;
private ProfileCache profileCache;
/**
* Construct objects. Actual loading occurs when the plugin is enabled, so
* this merely instantiates the objects.
*/
public WorldGuardPlugin() {
configuration = new ConfigurationManager(this);
globalRegionManager = new GlobalRegionManager(this);
final WorldGuardPlugin plugin = inst = this;
commands = new CommandsManager<CommandSender>() {
@Override
@ -131,6 +151,11 @@ public static WorldGuardPlugin inst() {
@Override
@SuppressWarnings("deprecation")
public void onEnable() {
configureLogger();
getDataFolder().mkdirs(); // Need to create the plugins/WorldGuard folder
executorService = MoreExecutors.listeningDecorator(EvenMoreExecutors.newBoundedCachedThreadPool(0, 1, 20));
// Set the proper command injector
commands.setInjector(new SimpleInjector(this));
@ -149,26 +174,43 @@ public void run() {
}
}, 0L);
// Need to create the plugins/WorldGuard folder
getDataFolder().mkdirs();
File cacheDir = new File(getDataFolder(), "cache");
cacheDir.mkdirs();
try {
profileCache = new SQLiteCache(new File(cacheDir, "profiles.sqlite"));
} catch (IOException e) {
log.log(Level.WARNING, "Failed to initialize SQLite profile cache");
profileCache = new HashMapCache();
}
profileService = new CacheForwardingService(
new CombinedProfileService(
BukkitPlayerService.getInstance(),
HttpRepositoryService.forMinecraft()),
profileCache);
PermissionsResolverManager.initialize(this);
// This must be done before configuration is loaded
LegacyWorldGuardMigration.migrateBlacklist(this);
try {
// Load the configuration
configuration.load();
globalRegionManager.preload();
} catch (FatalConfigurationLoadingException e) {
e.printStackTrace();
log.log(Level.WARNING, "Encountered fatal error while loading configuration", e);
getServer().shutdown();
log.log(Level.WARNING, "\n" +
"******************************************************\n" +
"* Failed to load WorldGuard configuration!\n" +
"* \n" +
"* Shutting down the server just in case...\n" +
"* \n" +
"* The error should be printed above this message. If you can't\n" +
"* figure out the problem, ask us on our forums:\n" +
"* http://forum.enginehub.org\n" +
"******************************************************\n");
}
// Migrate regions after the regions were loaded because
// the migration code reuses the loaded region managers
LegacyWorldGuardMigration.migrateRegions(this);
log.info("Loading region data...");
regionContainer.initialize();
flagStateManager = new FlagStateManager(this);
@ -190,7 +232,12 @@ public void run() {
(new BlacklistListener(this)).registerEvents();
(new ChestProtectionListener(this)).registerEvents();
(new RegionProtectionListener(this)).registerEvents();
(new RegionFlagsListener(this)).registerEvents();
(new BlockedPotionsListener(this)).registerEvents();
(new EventAbstractionListener(this)).registerEvents();
if ("true".equalsIgnoreCase(System.getProperty("worldguard.debug.listener"))) {
(new DebuggingListener(this, log)).registerEvents();
}
configuration.updateCommandBookGodMode();
@ -216,22 +263,38 @@ public void run() {
}
}
/**
* Called on plugin disable.
*/
@Override
public void onDisable() {
globalRegionManager.unload();
executorService.shutdown();
try {
log.log(Level.INFO, "Shutting down executor and waiting for any pending tasks...");
List<Task<?>> tasks = supervisor.getTasks();
if (!tasks.isEmpty()) {
StringBuilder builder = new StringBuilder("Known tasks:");
for (Task<?> task : tasks) {
builder.append("\n");
builder.append(task.getName());
}
log.log(Level.INFO, builder.toString());
}
Futures.successfulAsList(tasks).get();
executorService.awaitTermination(Integer.MAX_VALUE, TimeUnit.DAYS);
} catch (InterruptedException e) {
Thread.currentThread().interrupt();
} catch (ExecutionException e) {
log.log(Level.WARNING, "Some tasks failed while waiting for remaining tasks to finish", e);
}
regionContainer.unload();
configuration.unload();
this.getServer().getScheduler().cancelTasks(this);
}
/**
* Handle a command.
*/
@Override
public boolean onCommand(CommandSender sender, Command cmd, String label,
String[] args) {
public boolean onCommand(CommandSender sender, Command cmd, String label, String[] args) {
try {
commands.execute(cmd.getName(), args, sender, sender);
} catch (CommandPermissionsException e) {
@ -242,12 +305,7 @@ public boolean onCommand(CommandSender sender, Command cmd, String label,
sender.sendMessage(ChatColor.RED + e.getMessage());
sender.sendMessage(ChatColor.RED + e.getUsage());
} catch (WrappedCommandException e) {
if (e.getCause() instanceof NumberFormatException) {
sender.sendMessage(ChatColor.RED + "Number expected, string received instead.");
} else {
sender.sendMessage(ChatColor.RED + "An error has occurred. See console.");
e.printStackTrace();
}
sender.sendMessage(ChatColor.RED + convertThrowable(e.getCause()));
} catch (CommandException e) {
sender.sendMessage(ChatColor.RED + e.getMessage());
}
@ -255,15 +313,54 @@ public boolean onCommand(CommandSender sender, Command cmd, String label,
return true;
}
/**
* Convert the throwable into a somewhat friendly message.
*
* @param throwable the throwable
* @return a message
*/
public String convertThrowable(@Nullable Throwable throwable) {
if (throwable instanceof NumberFormatException) {
return "Number expected, string received instead.";
} else if (throwable instanceof StorageException) {
log.log(Level.WARNING, "Error loading/saving regions", throwable);
return "Region data could not be loaded/saved: " + throwable.getMessage();
} else if (throwable instanceof RejectedExecutionException) {
return "There are currently too many tasks queued to add yours. Use /wg running to list queued and running tasks.";
} else if (throwable instanceof CancellationException) {
return "WorldGuard: Task was cancelled";
} else if (throwable instanceof InterruptedException) {
return "WorldGuard: Task was interrupted";
} else if (throwable instanceof UnresolvedNamesException) {
return throwable.getMessage();
} else if (throwable instanceof CommandException) {
return throwable.getMessage();
} else {
log.log(Level.WARNING, "WorldGuard encountered an unexpected error", throwable);
return "WorldGuard: An unexpected error occurred! Please see the server console.";
}
}
/**
* Get the GlobalRegionManager.
*
* @return The plugin's global region manager
* @return the plugin's global region manager
* @deprecated use {@link #getRegionContainer()}
*/
@Deprecated
public GlobalRegionManager getGlobalRegionManager() {
return globalRegionManager;
}
/**
* Get the object that manages region data.
*
* @return the region container
*/
public RegionContainer getRegionContainer() {
return regionContainer;
}
/**
* Get the WorldGuard Configuration.
*
@ -293,6 +390,43 @@ public ConfigurationManager getGlobalStateManager() {
return configuration;
}
/**
* Get the supervisor.
*
* @return the supervisor
*/
public Supervisor getSupervisor() {
return supervisor;
}
/**
* Get the global executor service for internal usage (please use your
* own executor service).
*
* @return the global executor service
*/
public ListeningExecutorService getExecutorService() {
return executorService;
}
/**
* Get the profile lookup service.
*
* @return the profile lookup service
*/
public ProfileService getProfileService() {
return profileService;
}
/**
* Get the profile cache.
*
* @return the profile cache
*/
public ProfileCache getProfileCache() {
return profileCache;
}
/**
* Check whether a player is in a group.
* This calls the corresponding method in PermissionsResolverManager
@ -718,6 +852,25 @@ public LocalPlayer wrapPlayer(Player player) {
return new BukkitPlayer(this, player);
}
/**
* Wrap a player as a LocalPlayer.
*
* <p>This implementation is incomplete -- permissions cannot be checked.</p>
*
* @param player The player to wrap
* @return The wrapped player
*/
public LocalPlayer wrapOfflinePlayer(OfflinePlayer player) {
return new BukkitOfflinePlayer(player);
}
/**
* Configure WorldGuard's loggers.
*/
private void configureLogger() {
RecordMessagePrefixer.register(Logger.getLogger("com.sk89q.worldguard"), "[WorldGuard] ");
}
/**
* Create a default configuration file from the .jar.
*
@ -745,7 +898,7 @@ public void createDefaultConfiguration(File actual,
if (copy == null) throw new FileNotFoundException();
input = file.getInputStream(copy);
} catch (IOException e) {
getLogger().severe("Unable to read default configuration: " + defaultName);
log.severe("Unable to read default configuration: " + defaultName);
}
if (input != null) {
@ -759,7 +912,7 @@ public void createDefaultConfiguration(File actual,
output.write(buf, 0, length);
}
getLogger().info("Default configuration file written: "
log.info("Default configuration file written: "
+ actual.getAbsolutePath());
} catch (IOException e) {
e.printStackTrace();
@ -797,7 +950,7 @@ public void broadcastNotification(String msg) {
player.sendMessage(msg);
}
}
getLogger().info(msg);
log.info(msg);
}
/**
@ -881,4 +1034,5 @@ public String replaceMacros(CommandSender sender, String message) {
return message;
}
}

View File

@ -0,0 +1,233 @@
/*
* 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.cause;
import com.google.common.base.Joiner;
import com.sk89q.worldguard.bukkit.util.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.metadata.Metadatable;
import javax.annotation.Nullable;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import static com.google.common.base.Preconditions.checkNotNull;
/**
* An instance of this object describes the actors that played a role in
* causing an event, with the ability to describe a situation where one actor
* controls several other actors to create the event.
*
* <p>For example, if a player fires an arrow that hits an item frame, the player
* is the initiator, while the arrow is merely controlled by the player to
* hit the item frame.</p>
*/
public class Cause {
private static final String CAUSE_KEY = "worldguard.cause";
private static final Cause UNKNOWN = new Cause(Collections.emptyList());
private final List<Object> causes;
/**
* Create a new instance.
*
* @param causes a list of causes
*/
private Cause(List<Object> causes) {
checkNotNull(causes);
this.causes = causes;
}
/**
* Return whether a cause is known.
*
* @return true if known
*/
public boolean isKnown() {
return !causes.isEmpty();
}
@Nullable
public Object getRootCause() {
if (!causes.isEmpty()) {
return causes.get(0);
}
return null;
}
@Nullable
public Player getFirstPlayer() {
for (Object object : causes) {
if (object instanceof Player) {
return (Player) object;
}
}
return null;
}
@Nullable
public Entity getFirstEntity() {
for (Object object : causes) {
if (object instanceof Entity) {
return (Entity) object;
}
}
return null;
}
@Nullable
public Block getFirstBlock() {
for (Object object : causes) {
if (object instanceof Block) {
return (Block) object;
}
}
return null;
}
/**
* Find the first type matching one in the given array.
*
* @param types an array of types
* @return a found type or null
*/
@Nullable
public EntityType find(EntityType... types) {
for (Object object : causes) {
if (object instanceof Entity) {
for (EntityType type : types) {
if (((Entity) object).getType() == type) {
return type;
}
}
}
}
return null;
}
@Override
public String toString() {
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;
}
// 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);
}
}
if (o instanceof TNTPrimed) {
expand(list, ((TNTPrimed) o).getSource());
list.add(o);
} else if (o instanceof Projectile) {
expand(list, ((Projectile) o).getShooter());
list.add(o);
} else if (o instanceof Vehicle) {
expand(list, ((Vehicle) o).getPassenger());
list.add(o);
} else if (o instanceof Tameable) {
expand(list, ((Tameable) o).getOwner());
list.add(o);
} else {
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
* following it are controlled by the previous entry.
*
* @param cause an array of causing objects
* @return a 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);
} else {
return UNKNOWN;
}
}
/**
* Create a new instance that indicates that the cause is not known.
*
* @return a cause
*/
public static Cause unknown() {
return UNKNOWN;
}
/**
* Add a parent cause to a {@code Metadatable} object.
*
* <p>Note that {@code target} cannot be an instance of
* {@link Block} because {@link #create(Object...)} will not bother
* checking for such data on blocks (because it is relatively costly
* to do so).</p>
*
* @param target the target
* @param parent the parent cause
* @throws IllegalArgumentException thrown if {@code target} is an instance of {@link Block}
*/
public static void trackParentCause(Metadatable target, Object parent) {
if (target instanceof Block) {
throw new IllegalArgumentException("Can't track causes on Blocks because Cause doesn't check block metadata");
}
WGMetadata.put(target, CAUSE_KEY, parent);
}
}

View File

@ -0,0 +1,135 @@
/*
* WorldGuard, a suite of tools for Minecraft
* Copyright (C) sk89q <http://www.sk89q.com>
* Copyright (C) WorldGuard team and contributors
*
* This program is free software: you can redistribute it and/or modify it
* under the terms of the GNU Lesser General Public License as published by the
* Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License
* for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package com.sk89q.worldguard.bukkit.commands;
import com.google.common.util.concurrent.Futures;
import com.google.common.util.concurrent.ListenableFuture;
import com.sk89q.worldguard.util.task.FutureForwardingTask;
import com.sk89q.worldguard.bukkit.WorldGuardPlugin;
import org.bukkit.World;
import org.bukkit.command.CommandSender;
import javax.annotation.Nullable;
import static com.google.common.base.Preconditions.checkNotNull;
public class AsyncCommandHelper {
private final ListenableFuture<?> future;
private final WorldGuardPlugin plugin;
private final CommandSender sender;
@Nullable
private Object[] formatArgs;
private AsyncCommandHelper(ListenableFuture<?> future, WorldGuardPlugin plugin, CommandSender sender) {
checkNotNull(future);
checkNotNull(plugin);
checkNotNull(sender);
this.future = future;
this.plugin = plugin;
this.sender = sender;
}
public AsyncCommandHelper formatUsing(Object... args) {
this.formatArgs = args;
return this;
}
private String format(String message) {
if (formatArgs != null) {
return String.format(message, formatArgs);
} else {
return message;
}
}
public AsyncCommandHelper registerWithSupervisor(String description) {
plugin.getSupervisor().monitor(
FutureForwardingTask.create(
future, format(description), sender));
return this;
}
public AsyncCommandHelper sendMessageAfterDelay(String message) {
FutureProgressListener.addProgressListener(future, sender, format(message));
return this;
}
public AsyncCommandHelper thenRespondWith(String success, String failure) {
// Send a response message
Futures.addCallback(
future,
new MessageFutureCallback.Builder(plugin, sender)
.onSuccess(format(success))
.onFailure(format(failure))
.build());
return this;
}
public AsyncCommandHelper thenTellErrorsOnly(String failure) {
// Send a response message
Futures.addCallback(
future,
new MessageFutureCallback.Builder(plugin, sender)
.onFailure(format(failure))
.build());
return this;
}
public AsyncCommandHelper forRegionDataLoad(World world, boolean silent) {
checkNotNull(world);
formatUsing(world.getName());
registerWithSupervisor("Loading region data for '%s'");
if (silent) {
thenTellErrorsOnly("Failed to load regions '%s'");
} else {
sendMessageAfterDelay("(Please wait... loading the region data for '%s')");
thenRespondWith(
"Loaded region data for '%s'",
"Failed to load regions '%s'");
}
return this;
}
public AsyncCommandHelper forRegionDataSave(World world, boolean silent) {
checkNotNull(world);
formatUsing(world.getName());
registerWithSupervisor("Saving region data for '%s'");
if (silent) {
thenTellErrorsOnly("Failed to save regions '%s'");
} else {
sendMessageAfterDelay("(Please wait... saving the region data for '%s')");
thenRespondWith(
"Saved region data for '%s'",
"Failed to load regions '%s'");
}
return this;
}
public static AsyncCommandHelper wrap(ListenableFuture<?> future, WorldGuardPlugin plugin, CommandSender sender) {
return new AsyncCommandHelper(future, plugin, sender);
}
}

View File

@ -0,0 +1,146 @@
/*
* WorldGuard, a suite of tools for Minecraft
* Copyright (C) sk89q <http://www.sk89q.com>
* Copyright (C) WorldGuard team and contributors
*
* This program is free software: you can redistribute it and/or modify it
* under the terms of the GNU Lesser General Public License as published by the
* Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License
* for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package com.sk89q.worldguard.bukkit.commands;
import com.google.common.base.Function;
import org.bukkit.ChatColor;
import org.bukkit.command.BlockCommandSender;
import org.bukkit.command.CommandSender;
import org.bukkit.command.ConsoleCommandSender;
import org.bukkit.entity.Player;
import javax.annotation.Nullable;
/**
* Command-related utility methods.
*/
public final class CommandUtils {
private CommandUtils() {
}
/**
* Replace color macros in a string.
*
* @param str the string
* @return the new string
*/
public static String replaceColorMacros(String str) {
// TODO: Make this more efficient
str = str.replace("`r", ChatColor.RED.toString());
str = str.replace("`R", ChatColor.DARK_RED.toString());
str = str.replace("`y", ChatColor.YELLOW.toString());
str = str.replace("`Y", ChatColor.GOLD.toString());
str = str.replace("`g", ChatColor.GREEN.toString());
str = str.replace("`G", ChatColor.DARK_GREEN.toString());
str = str.replace("`c", ChatColor.AQUA.toString());
str = str.replace("`C", ChatColor.DARK_AQUA.toString());
str = str.replace("`b", ChatColor.BLUE.toString());
str = str.replace("`B", ChatColor.DARK_BLUE.toString());
str = str.replace("`p", ChatColor.LIGHT_PURPLE.toString());
str = str.replace("`P", ChatColor.DARK_PURPLE.toString());
str = str.replace("`0", ChatColor.BLACK.toString());
str = str.replace("`1", ChatColor.DARK_GRAY.toString());
str = str.replace("`2", ChatColor.GRAY.toString());
str = str.replace("`w", ChatColor.WHITE.toString());
str = str.replace("`k", ChatColor.MAGIC.toString());
str = str.replace("`l", ChatColor.BOLD.toString());
str = str.replace("`m", ChatColor.STRIKETHROUGH.toString());
str = str.replace("`n", ChatColor.UNDERLINE.toString());
str = str.replace("`o", ChatColor.ITALIC.toString());
str = str.replace("`x", ChatColor.RESET.toString());
// MC classic
str = str.replace("&c", ChatColor.RED.toString());
str = str.replace("&4", ChatColor.DARK_RED.toString());
str = str.replace("&e", ChatColor.YELLOW.toString());
str = str.replace("&6", ChatColor.GOLD.toString());
str = str.replace("&a", ChatColor.GREEN.toString());
str = str.replace("&2", ChatColor.DARK_GREEN.toString());
str = str.replace("&b", ChatColor.AQUA.toString());
str = str.replace("&3", ChatColor.DARK_AQUA.toString());
str = str.replace("&9", ChatColor.BLUE.toString());
str = str.replace("&1", ChatColor.DARK_BLUE.toString());
str = str.replace("&d", ChatColor.LIGHT_PURPLE.toString());
str = str.replace("&5", ChatColor.DARK_PURPLE.toString());
str = str.replace("&0", ChatColor.BLACK.toString());
str = str.replace("&8", ChatColor.DARK_GRAY.toString());
str = str.replace("&7", ChatColor.GRAY.toString());
str = str.replace("&f", ChatColor.WHITE.toString());
return str;
}
/**
* Get the name of the given owner object.
*
* @param owner the owner object
* @return a name
*/
public static String getOwnerName(@Nullable Object owner) {
if (owner == null) {
return "?";
} else if (owner instanceof Player) {
return ((Player) owner).getName();
} else if (owner instanceof ConsoleCommandSender) {
return "*CONSOLE*";
} else if (owner instanceof BlockCommandSender) {
return ((BlockCommandSender) owner).getBlock().getLocation().toString();
} else {
return "?";
}
}
/**
* Return a function that accepts a string to send a message to the
* given sender.
*
* @param sender the sender
* @return a function
*/
public static Function<String, ?> messageFunction(final CommandSender sender) {
return new Function<String, Object>() {
@Override
public Object apply(@Nullable String s) {
sender.sendMessage(s);
return null;
}
};
}
}

View File

@ -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.bukkit.commands;
import com.google.common.util.concurrent.ListenableFuture;
import com.google.common.util.concurrent.MoreExecutors;
import org.bukkit.ChatColor;
import org.bukkit.command.CommandSender;
import java.util.Timer;
import static com.google.common.base.Preconditions.checkNotNull;
public class FutureProgressListener implements Runnable {
private static final Timer timer = new Timer();
private static final int MESSAGE_DELAY = 1000;
private final MessageTimerTask task;
public FutureProgressListener(CommandSender sender, String message) {
checkNotNull(sender);
checkNotNull(message);
task = new MessageTimerTask(sender, ChatColor.GRAY + message);
timer.schedule(task, MESSAGE_DELAY);
}
@Override
public void run() {
task.cancel();
}
public static void addProgressListener(ListenableFuture<?> future, CommandSender sender, String message) {
future.addListener(new FutureProgressListener(sender, message), MoreExecutors.sameThreadExecutor());
}
}

View File

@ -0,0 +1,103 @@
/*
* WorldGuard, a suite of tools for Minecraft
* Copyright (C) sk89q <http://www.sk89q.com>
* Copyright (C) WorldGuard team and contributors
*
* This program is free software: you can redistribute it and/or modify it
* under the terms of the GNU Lesser General Public License as published by the
* Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License
* for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package com.sk89q.worldguard.bukkit.commands;
import com.google.common.util.concurrent.FutureCallback;
import com.sk89q.worldguard.bukkit.WorldGuardPlugin;
import org.bukkit.ChatColor;
import org.bukkit.command.CommandSender;
import javax.annotation.Nullable;
import static com.google.common.base.Preconditions.checkNotNull;
public class MessageFutureCallback<V> implements FutureCallback<V> {
private final WorldGuardPlugin plugin;
private final CommandSender sender;
@Nullable
private final String success;
@Nullable
private final String failure;
private MessageFutureCallback(WorldGuardPlugin plugin, CommandSender sender, @Nullable String success, @Nullable String failure) {
this.plugin = plugin;
this.sender = sender;
this.success = success;
this.failure = failure;
}
@Override
public void onSuccess(@Nullable V v) {
if (success != null) {
sender.sendMessage(ChatColor.YELLOW + success);
}
}
@Override
public void onFailure(@Nullable Throwable throwable) {
String failure = this.failure != null ? this.failure : "An error occurred";
sender.sendMessage(ChatColor.RED + failure + ": " + plugin.convertThrowable(throwable));
}
public static class Builder {
private final WorldGuardPlugin plugin;
private final CommandSender sender;
@Nullable
private String success;
@Nullable
private String failure;
public Builder(WorldGuardPlugin plugin, CommandSender sender) {
checkNotNull(plugin);
checkNotNull(sender);
this.plugin = plugin;
this.sender = sender;
}
public Builder onSuccess(@Nullable String message) {
this.success = message;
return this;
}
public Builder onFailure(@Nullable String message) {
this.failure = message;
return this;
}
public <V> MessageFutureCallback<V> build() {
return new MessageFutureCallback<V>(plugin, sender, success, failure);
}
}
public static <V> MessageFutureCallback<V> createRegionLoadCallback(WorldGuardPlugin plugin, CommandSender sender) {
return new Builder(plugin, sender)
.onSuccess("Successfully load the region data.")
.build();
}
public static <V> MessageFutureCallback<V> createRegionSaveCallback(WorldGuardPlugin plugin, CommandSender sender) {
return new Builder(plugin, sender)
.onSuccess("Successfully saved the region data.")
.build();
}
}

View File

@ -17,32 +17,30 @@
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package com.sk89q.worldguard.internal.cause;
package com.sk89q.worldguard.bukkit.commands;
import org.bukkit.entity.Player;
import org.bukkit.command.CommandSender;
import java.util.TimerTask;
import static com.google.common.base.Preconditions.checkNotNull;
/**
* A cause that is the player.
*/
public class PlayerCause implements Cause<Player> {
public class MessageTimerTask extends TimerTask {
private final Player player;
private final CommandSender sender;
private final String message;
/**
* Create a new instance.
*
* @param player the player
*/
public PlayerCause(Player player) {
checkNotNull(player);
this.player = player;
MessageTimerTask(CommandSender sender, String message) {
checkNotNull(sender);
checkNotNull(message);
this.sender = sender;
this.message = message;
}
@Override
public Player get() {
return player;
public void run() {
sender.sendMessage(message);
}
}

View File

@ -19,6 +19,8 @@
package com.sk89q.worldguard.bukkit.commands;
import com.sk89q.worldguard.bukkit.commands.region.MemberCommands;
import com.sk89q.worldguard.bukkit.commands.region.RegionCommands;
import org.bukkit.command.CommandSender;
import com.sk89q.minecraft.util.commands.Command;
@ -35,7 +37,7 @@ public ProtectionCommands(WorldGuardPlugin plugin) {
}
@Command(aliases = {"region", "regions", "rg"}, desc = "Region management commands")
@NestedCommand({RegionCommands.class, RegionMemberCommands.class})
@NestedCommand({RegionCommands.class, MemberCommands.class})
public void region(CommandContext args, CommandSender sender) {}
@Command(aliases = {"worldguard", "wg"}, desc = "WorldGuard commands")

View File

@ -1,59 +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.commands;
/**
* Used for /rg list.
*/
class RegionListEntry implements Comparable<RegionListEntry> {
private final String id;
private final int index;
boolean isOwner;
boolean isMember;
public RegionListEntry(String id, int index) {
this.id = id;
this.index = index;
}
@Override
public int compareTo(RegionListEntry o) {
if (isOwner != o.isOwner) {
return isOwner ? 1 : -1;
}
if (isMember != o.isMember) {
return isMember ? 1 : -1;
}
return id.compareTo(o.id);
}
@Override
public String toString() {
if (isOwner) {
return (index + 1) + ". +" + id;
} else if (isMember) {
return (index + 1) + ". -" + id;
} else {
return (index + 1) + ". " + id;
}
}
}

View File

@ -1,303 +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.commands;
import org.bukkit.ChatColor;
import org.bukkit.World;
import org.bukkit.command.CommandSender;
import org.bukkit.entity.Player;
import com.sk89q.minecraft.util.commands.Command;
import com.sk89q.minecraft.util.commands.CommandContext;
import com.sk89q.minecraft.util.commands.CommandException;
import com.sk89q.worldguard.LocalPlayer;
import com.sk89q.worldguard.bukkit.WorldGuardPlugin;
import com.sk89q.worldguard.domains.DefaultDomain;
import com.sk89q.worldguard.protection.databases.ProtectionDatabaseException;
import com.sk89q.worldguard.protection.databases.RegionDBUtil;
import com.sk89q.worldguard.protection.flags.DefaultFlag;
import com.sk89q.worldguard.protection.managers.RegionManager;
import com.sk89q.worldguard.protection.regions.ProtectedRegion;
// @TODO: A lot of code duplication here! Need to fix.
public class RegionMemberCommands {
private final WorldGuardPlugin plugin;
public RegionMemberCommands(WorldGuardPlugin plugin) {
this.plugin = plugin;
}
@Command(aliases = {"addmember", "addmember", "addmem", "am"},
usage = "<id> <members...>",
flags = "w:",
desc = "Add a member to a region",
min = 2)
public void addMember(CommandContext args, CommandSender sender) throws CommandException {
final World world;
Player player = null;
LocalPlayer localPlayer = null;
if (sender instanceof Player) {
player = (Player) sender;
localPlayer = plugin.wrapPlayer(player);
}
if (args.hasFlag('w')) {
world = plugin.matchWorld(sender, args.getFlag('w'));
} else {
if (player != null) {
world = player.getWorld();
} else {
throw new CommandException("No world specified. Use -w <worldname>.");
}
}
String id = args.getString(0);
RegionManager mgr = plugin.getGlobalRegionManager().get(world);
ProtectedRegion region = mgr.getRegion(id);
if (region == null) {
throw new CommandException("Could not find a region by that ID.");
}
id = region.getId();
if (localPlayer != null) {
if (region.isOwner(localPlayer)) {
plugin.checkPermission(sender, "worldguard.region.addmember.own." + id.toLowerCase());
} else if (region.isMember(localPlayer)) {
plugin.checkPermission(sender, "worldguard.region.addmember.member." + id.toLowerCase());
} else {
plugin.checkPermission(sender, "worldguard.region.addmember." + id.toLowerCase());
}
}
RegionDBUtil.addToDomain(region.getMembers(), args.getParsedPaddedSlice(1, 0), 0);
sender.sendMessage(ChatColor.YELLOW
+ "Region '" + id + "' updated.");
try {
mgr.save();
} catch (ProtectionDatabaseException e) {
throw new CommandException("Failed to write regions: "
+ e.getMessage());
}
}
@Command(aliases = {"addowner", "addowner", "ao"},
usage = "<id> <owners...>",
flags = "w:",
desc = "Add an owner to a region",
min = 2)
public void addOwner(CommandContext args, CommandSender sender) throws CommandException {
final World world;
Player player = null;
LocalPlayer localPlayer = null;
if (sender instanceof Player) {
player = (Player) sender;
localPlayer = plugin.wrapPlayer(player);
}
if (args.hasFlag('w')) {
world = plugin.matchWorld(sender, args.getFlag('w'));
} else {
if (player != null) {
world = player.getWorld();
} else {
throw new CommandException("No world specified. Use -w <worldname>.");
}
}
String id = args.getString(0);
RegionManager mgr = plugin.getGlobalRegionManager().get(world);
ProtectedRegion region = mgr.getRegion(id);
if (region == null) {
throw new CommandException("Could not find a region by that ID.");
}
id = region.getId();
Boolean flag = region.getFlag(DefaultFlag.BUYABLE);
DefaultDomain owners = region.getOwners();
if (localPlayer != null) {
if (flag != null && flag && owners != null && owners.size() == 0) {
if (!plugin.hasPermission(player, "worldguard.region.unlimited")) {
int maxRegionCount = plugin.getGlobalStateManager().get(world).getMaxRegionCount(player);
if (maxRegionCount >= 0 && mgr.getRegionCountOfPlayer(localPlayer)
>= maxRegionCount) {
throw new CommandException("You already own the maximum allowed amount of regions.");
}
}
plugin.checkPermission(sender, "worldguard.region.addowner.unclaimed." + id.toLowerCase());
} else {
if (region.isOwner(localPlayer)) {
plugin.checkPermission(sender, "worldguard.region.addowner.own." + id.toLowerCase());
} else if (region.isMember(localPlayer)) {
plugin.checkPermission(sender, "worldguard.region.addowner.member." + id.toLowerCase());
} else {
plugin.checkPermission(sender, "worldguard.region.addowner." + id.toLowerCase());
}
}
}
RegionDBUtil.addToDomain(region.getOwners(), args.getParsedPaddedSlice(1, 0), 0);
sender.sendMessage(ChatColor.YELLOW
+ "Region '" + id + "' updated.");
try {
mgr.save();
} catch (ProtectionDatabaseException e) {
throw new CommandException("Failed to write regions: "
+ e.getMessage());
}
}
@Command(aliases = {"removemember", "remmember", "removemem", "remmem", "rm"},
usage = "<id> <owners...>",
flags = "aw:",
desc = "Remove an owner to a region",
min = 1)
public void removeMember(CommandContext args, CommandSender sender) throws CommandException {
final World world;
Player player = null;
LocalPlayer localPlayer = null;
if (sender instanceof Player) {
player = (Player) sender;
localPlayer = plugin.wrapPlayer(player);
}
if (args.hasFlag('w')) {
world = plugin.matchWorld(sender, args.getFlag('w'));
} else {
if (player != null) {
world = player.getWorld();
} else {
throw new CommandException("No world specified. Use -w <worldname>.");
}
}
String id = args.getString(0);
RegionManager mgr = plugin.getGlobalRegionManager().get(world);
ProtectedRegion region = mgr.getRegion(id);
if (region == null) {
throw new CommandException("Could not find a region by that ID.");
}
id = region.getId();
if (localPlayer != null) {
if (region.isOwner(localPlayer)) {
plugin.checkPermission(sender, "worldguard.region.removemember.own." + id.toLowerCase());
} else if (region.isMember(localPlayer)) {
plugin.checkPermission(sender, "worldguard.region.removemember.member." + id.toLowerCase());
} else {
plugin.checkPermission(sender, "worldguard.region.removemember." + id.toLowerCase());
}
}
if (args.hasFlag('a')) {
region.getMembers().removeAll();
} else {
if (args.argsLength() < 2) {
throw new CommandException("List some names to remove, or use -a to remove all.");
}
RegionDBUtil.removeFromDomain(region.getMembers(), args.getParsedPaddedSlice(1, 0), 0);
}
sender.sendMessage(ChatColor.YELLOW
+ "Region '" + id + "' updated.");
try {
mgr.save();
} catch (ProtectionDatabaseException e) {
throw new CommandException("Failed to write regions: "
+ e.getMessage());
}
}
@Command(aliases = {"removeowner", "remowner", "ro"},
usage = "<id> <owners...>",
flags = "aw:",
desc = "Remove an owner to a region",
min = 1)
public void removeOwner(CommandContext args,
CommandSender sender) throws CommandException {
final World world;
Player player = null;
LocalPlayer localPlayer = null;
if (sender instanceof Player) {
player = (Player) sender;
localPlayer = plugin.wrapPlayer(player);
}
if (args.hasFlag('w')) {
world = plugin.matchWorld(sender, args.getFlag('w'));
} else {
if (player != null) {
world = player.getWorld();
} else {
throw new CommandException("No world specified. Use -w <worldname>.");
}
}
String id = args.getString(0);
RegionManager mgr = plugin.getGlobalRegionManager().get(world);
ProtectedRegion region = mgr.getRegion(id);
if (region == null) {
throw new CommandException("Could not find a region by that ID.");
}
id = region.getId();
if (localPlayer != null) {
if (region.isOwner(localPlayer)) {
plugin.checkPermission(sender, "worldguard.region.removeowner.own." + id.toLowerCase());
} else if (region.isMember(localPlayer)) {
plugin.checkPermission(sender, "worldguard.region.removeowner.member." + id.toLowerCase());
} else {
plugin.checkPermission(sender, "worldguard.region.removeowner." + id.toLowerCase());
}
}
if (args.hasFlag('a')) {
region.getOwners().removeAll();
} else {
if (args.argsLength() < 2) {
throw new CommandException("List some names to remove, or use -a to remove all.");
}
RegionDBUtil.removeFromDomain(region.getOwners(), args.getParsedPaddedSlice(1, 0), 0);
}
sender.sendMessage(ChatColor.YELLOW
+ "Region '" + id + "' updated.");
try {
mgr.save();
} catch (ProtectionDatabaseException e) {
throw new CommandException("Failed to write regions: "
+ e.getMessage());
}
}
}

View File

@ -19,24 +19,27 @@
package com.sk89q.worldguard.bukkit.commands;
import java.io.File;
import java.io.IOException;
import java.util.logging.Level;
import java.util.logging.Logger;
import org.bukkit.ChatColor;
import org.bukkit.command.CommandSender;
import org.bukkit.entity.Player;
import com.sk89q.minecraft.util.commands.Command;
import com.sk89q.minecraft.util.commands.CommandContext;
import com.sk89q.minecraft.util.commands.CommandException;
import com.sk89q.minecraft.util.commands.CommandPermissions;
import com.sk89q.worldguard.bukkit.LoggerToChatHandler;
import com.sk89q.worldguard.bukkit.ReportWriter;
import com.sk89q.worldguard.util.task.Task;
import com.sk89q.worldguard.util.task.TaskStateComparator;
import com.sk89q.worldguard.bukkit.util.LoggerToChatHandler;
import com.sk89q.worldguard.bukkit.util.ReportWriter;
import com.sk89q.worldguard.bukkit.WorldGuardPlugin;
import com.sk89q.worldguard.util.PastebinPoster;
import com.sk89q.worldguard.util.PastebinPoster.PasteCallback;
import org.bukkit.ChatColor;
import org.bukkit.command.CommandSender;
import org.bukkit.entity.Player;
import java.io.File;
import java.io.IOException;
import java.util.Collections;
import java.util.List;
import java.util.logging.Level;
import java.util.logging.Logger;
public class WorldGuardCommands {
private final WorldGuardPlugin plugin;
@ -56,6 +59,11 @@ public void version(CommandContext args, CommandSender sender) throws CommandExc
@Command(aliases = {"reload"}, desc = "Reload WorldGuard configuration", max = 0)
@CommandPermissions({"worldguard.reload"})
public void reload(CommandContext args, CommandSender sender) throws CommandException {
// TODO: This is subject to a race condition, but at least other commands are not being processed concurrently
List<Task<?>> tasks = plugin.getSupervisor().getTasks();
if (!tasks.isEmpty()) {
throw new CommandException("There are currently pending tasks. Use /wg running to monitor these tasks first.");
}
LoggerToChatHandler handler = null;
Logger minecraftLogger = null;
@ -63,15 +71,14 @@ public void reload(CommandContext args, CommandSender sender) throws CommandExce
if (sender instanceof Player) {
handler = new LoggerToChatHandler(sender);
handler.setLevel(Level.ALL);
minecraftLogger = Logger.getLogger("Minecraft");
minecraftLogger = Logger.getLogger("com.sk89q.worldguard");
minecraftLogger.addHandler(handler);
}
try {
plugin.getGlobalStateManager().unload();
plugin.getGlobalRegionManager().unload();
plugin.getRegionContainer().reload();
plugin.getGlobalStateManager().load();
plugin.getGlobalRegionManager().preload();
// WGBukkit.cleanCache();
sender.sendMessage("WorldGuard configuration reloaded.");
} catch (Throwable t) {
@ -135,4 +142,32 @@ public void flushStates(CommandContext args, CommandSender sender) throws Comman
}
}
@Command(aliases = {"running", "queue"}, desc = "List running tasks", max = 0)
@CommandPermissions("worldguard.running")
public void listRunningTasks(CommandContext args, CommandSender sender) throws CommandException {
List<Task<?>> tasks = plugin.getSupervisor().getTasks();
if (!tasks.isEmpty()) {
Collections.sort(tasks, new TaskStateComparator());
StringBuilder builder = new StringBuilder();
builder.append(ChatColor.GRAY);
builder.append("\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550");
builder.append(" Running tasks ");
builder.append("\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550");
builder.append("\n").append(ChatColor.GRAY).append("Note: Some 'running' tasks may be waiting to be start.");
for (Task task : tasks) {
builder.append("\n");
builder.append(ChatColor.BLUE).append("(").append(task.getState().name()).append(") ");
builder.append(ChatColor.YELLOW);
builder.append(CommandUtils.getOwnerName(task.getOwner()));
builder.append(": ");
builder.append(ChatColor.WHITE);
builder.append(task.getName());
}
sender.sendMessage(builder.toString());
} else {
sender.sendMessage(ChatColor.YELLOW + "There are currently no running tasks.");
}
}
}

View File

@ -0,0 +1,242 @@
/*
* WorldGuard, a suite of tools for Minecraft
* Copyright (C) sk89q <http://www.sk89q.com>
* Copyright (C) WorldGuard team and contributors
*
* This program is free software: you can redistribute it and/or modify it
* under the terms of the GNU Lesser General Public License as published by the
* Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License
* for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package com.sk89q.worldguard.bukkit.commands.region;
import com.google.common.util.concurrent.Futures;
import com.google.common.util.concurrent.ListenableFuture;
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.CommandPermissionsException;
import com.sk89q.worldguard.LocalPlayer;
import com.sk89q.worldguard.bukkit.WorldGuardPlugin;
import com.sk89q.worldguard.bukkit.commands.AsyncCommandHelper;
import com.sk89q.worldguard.domains.DefaultDomain;
import com.sk89q.worldguard.protection.util.DomainInputResolver;
import com.sk89q.worldguard.protection.util.DomainInputResolver.UserLocatorPolicy;
import com.sk89q.worldguard.protection.flags.DefaultFlag;
import com.sk89q.worldguard.protection.managers.RegionManager;
import com.sk89q.worldguard.protection.regions.ProtectedRegion;
import org.bukkit.World;
import org.bukkit.command.CommandSender;
import org.bukkit.entity.Player;
public class MemberCommands extends RegionCommandsBase {
private final WorldGuardPlugin plugin;
public MemberCommands(WorldGuardPlugin plugin) {
this.plugin = plugin;
}
@Command(aliases = {"addmember", "addmember", "addmem", "am"},
usage = "<id> <members...>",
flags = "nw:",
desc = "Add a member to a region",
min = 2)
public void addMember(CommandContext args, CommandSender sender) throws CommandException {
warnAboutSaveFailures(sender);
World world = checkWorld(args, sender, 'w'); // Get the world
String id = args.getString(0);
RegionManager manager = checkRegionManager(plugin, world);
ProtectedRegion region = checkExistingRegion(manager, id, true);
id = region.getId();
// Check permissions
if (!getPermissionModel(sender).mayAddMembers(region)) {
throw new CommandPermissionsException();
}
// Resolve members asynchronously
DomainInputResolver resolver = new DomainInputResolver(
plugin.getProfileService(), args.getParsedPaddedSlice(1, 0));
resolver.setLocatorPolicy(args.hasFlag('n') ? UserLocatorPolicy.NAME_ONLY : UserLocatorPolicy.UUID_ONLY);
// Then add it to the members
ListenableFuture<DefaultDomain> future = Futures.transform(
plugin.getExecutorService().submit(resolver),
resolver.createAddAllFunction(region.getMembers()));
AsyncCommandHelper.wrap(future, plugin, sender)
.formatUsing(region.getId(), world.getName())
.registerWithSupervisor("Adding members to the region '%s' on '%s'")
.sendMessageAfterDelay("(Please wait... querying player names...)")
.thenRespondWith("Region '%s' updated with new members.", "Failed to add new members");
}
@Command(aliases = {"addowner", "addowner", "ao"},
usage = "<id> <owners...>",
flags = "nw:",
desc = "Add an owner to a region",
min = 2)
public void addOwner(CommandContext args, CommandSender sender) throws CommandException {
warnAboutSaveFailures(sender);
World world = checkWorld(args, sender, 'w'); // Get the world
Player player = null;
LocalPlayer localPlayer = null;
if (sender instanceof Player) {
player = (Player) sender;
localPlayer = plugin.wrapPlayer(player);
}
String id = args.getString(0);
RegionManager manager = checkRegionManager(plugin, world);
ProtectedRegion region = checkExistingRegion(manager, id, true);
id = region.getId();
Boolean flag = region.getFlag(DefaultFlag.BUYABLE);
DefaultDomain owners = region.getOwners();
if (localPlayer != null) {
if (flag != null && flag && owners != null && owners.size() == 0) {
// TODO: Move this to an event
if (!plugin.hasPermission(player, "worldguard.region.unlimited")) {
int maxRegionCount = plugin.getGlobalStateManager().get(world).getMaxRegionCount(player);
if (maxRegionCount >= 0 && manager.getRegionCountOfPlayer(localPlayer)
>= maxRegionCount) {
throw new CommandException("You already own the maximum allowed amount of regions.");
}
}
plugin.checkPermission(sender, "worldguard.region.addowner.unclaimed." + id.toLowerCase());
} else {
// Check permissions
if (!getPermissionModel(sender).mayAddOwners(region)) {
throw new CommandPermissionsException();
}
}
}
// Resolve owners asynchronously
DomainInputResolver resolver = new DomainInputResolver(
plugin.getProfileService(), args.getParsedPaddedSlice(1, 0));
resolver.setLocatorPolicy(args.hasFlag('n') ? UserLocatorPolicy.NAME_ONLY : UserLocatorPolicy.UUID_ONLY);
// Then add it to the owners
ListenableFuture<DefaultDomain> future = Futures.transform(
plugin.getExecutorService().submit(resolver),
resolver.createAddAllFunction(region.getOwners()));
AsyncCommandHelper.wrap(future, plugin, sender)
.formatUsing(region.getId(), world.getName())
.registerWithSupervisor("Adding owners to the region '%s' on '%s'")
.sendMessageAfterDelay("(Please wait... querying player names...)")
.thenRespondWith("Region '%s' updated with new owners.", "Failed to add new owners");
}
@Command(aliases = {"removemember", "remmember", "removemem", "remmem", "rm"},
usage = "<id> <owners...>",
flags = "naw:",
desc = "Remove an owner to a region",
min = 1)
public void removeMember(CommandContext args, CommandSender sender) throws CommandException {
warnAboutSaveFailures(sender);
World world = checkWorld(args, sender, 'w'); // Get the world
String id = args.getString(0);
RegionManager manager = checkRegionManager(plugin, world);
ProtectedRegion region = checkExistingRegion(manager, id, true);
// Check permissions
if (!getPermissionModel(sender).mayRemoveMembers(region)) {
throw new CommandPermissionsException();
}
ListenableFuture<?> future;
if (args.hasFlag('a')) {
region.getMembers().removeAll();
future = Futures.immediateFuture(null);
} else {
if (args.argsLength() < 2) {
throw new CommandException("List some names to remove, or use -a to remove all.");
}
// Resolve members asynchronously
DomainInputResolver resolver = new DomainInputResolver(
plugin.getProfileService(), args.getParsedPaddedSlice(1, 0));
resolver.setLocatorPolicy(args.hasFlag('n') ? UserLocatorPolicy.NAME_ONLY : UserLocatorPolicy.UUID_AND_NAME);
// Then remove it from the members
future = Futures.transform(
plugin.getExecutorService().submit(resolver),
resolver.createRemoveAllFunction(region.getMembers()));
}
AsyncCommandHelper.wrap(future, plugin, sender)
.formatUsing(region.getId(), world.getName())
.registerWithSupervisor("Removing members from the region '%s' on '%s'")
.sendMessageAfterDelay("(Please wait... querying player names...)")
.thenRespondWith("Region '%s' updated with members removed.", "Failed to remove members");
}
@Command(aliases = {"removeowner", "remowner", "ro"},
usage = "<id> <owners...>",
flags = "naw:",
desc = "Remove an owner to a region",
min = 1)
public void removeOwner(CommandContext args, CommandSender sender) throws CommandException {
warnAboutSaveFailures(sender);
World world = checkWorld(args, sender, 'w'); // Get the world
String id = args.getString(0);
RegionManager manager = checkRegionManager(plugin, world);
ProtectedRegion region = checkExistingRegion(manager, id, true);
// Check permissions
if (!getPermissionModel(sender).mayRemoveOwners(region)) {
throw new CommandPermissionsException();
}
ListenableFuture<?> future;
if (args.hasFlag('a')) {
region.getOwners().removeAll();
future = Futures.immediateFuture(null);
} else {
if (args.argsLength() < 2) {
throw new CommandException("List some names to remove, or use -a to remove all.");
}
// Resolve owners asynchronously
DomainInputResolver resolver = new DomainInputResolver(
plugin.getProfileService(), args.getParsedPaddedSlice(1, 0));
resolver.setLocatorPolicy(args.hasFlag('n') ? UserLocatorPolicy.NAME_ONLY : UserLocatorPolicy.UUID_AND_NAME);
// Then remove it from the owners
future = Futures.transform(
plugin.getExecutorService().submit(resolver),
resolver.createRemoveAllFunction(region.getOwners()));
}
AsyncCommandHelper.wrap(future, plugin, sender)
.formatUsing(region.getId(), world.getName())
.registerWithSupervisor("Removing owners from the region '%s' on '%s'")
.sendMessageAfterDelay("(Please wait... querying player names...)")
.thenRespondWith("Region '%s' updated with owners removed.", "Failed to remove owners");
}
}

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,397 @@
/*
* WorldGuard, a suite of tools for Minecraft
* Copyright (C) sk89q <http://www.sk89q.com>
* Copyright (C) WorldGuard team and contributors
*
* This program is free software: you can redistribute it and/or modify it
* under the terms of the GNU Lesser General Public License as published by the
* Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License
* for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package com.sk89q.worldguard.bukkit.commands.region;
import com.google.common.base.Function;
import com.google.common.base.Joiner;
import com.google.common.collect.Iterables;
import com.sk89q.minecraft.util.commands.CommandContext;
import com.sk89q.minecraft.util.commands.CommandException;
import com.sk89q.worldedit.BlockVector;
import com.sk89q.worldedit.Vector;
import com.sk89q.worldedit.bukkit.WorldEditPlugin;
import com.sk89q.worldedit.bukkit.selections.CuboidSelection;
import com.sk89q.worldedit.bukkit.selections.Polygonal2DSelection;
import com.sk89q.worldedit.bukkit.selections.Selection;
import com.sk89q.worldguard.bukkit.RegionContainer;
import com.sk89q.worldguard.bukkit.WorldGuardPlugin;
import com.sk89q.worldguard.bukkit.permission.RegionPermissionModel;
import com.sk89q.worldguard.protection.ApplicableRegionSet;
import com.sk89q.worldguard.protection.flags.Flag;
import com.sk89q.worldguard.protection.flags.InvalidFlagFormat;
import com.sk89q.worldguard.protection.managers.RegionManager;
import com.sk89q.worldguard.protection.regions.GlobalProtectedRegion;
import com.sk89q.worldguard.protection.regions.ProtectedCuboidRegion;
import com.sk89q.worldguard.protection.regions.ProtectedPolygonalRegion;
import com.sk89q.worldguard.protection.regions.ProtectedRegion;
import org.bukkit.ChatColor;
import org.bukkit.World;
import org.bukkit.command.CommandSender;
import org.bukkit.entity.Player;
import java.util.Set;
class RegionCommandsBase {
protected RegionCommandsBase() {
}
/**
* Get the permission model to lookup permissions.
*
* @param sender the sender
* @return the permission model
*/
protected static RegionPermissionModel getPermissionModel(CommandSender sender) {
return new RegionPermissionModel(WorldGuardPlugin.inst(), sender);
}
/**
* Gets the world from the given flag, or falling back to the the current player
* if the sender is a player, otherwise reporting an error.
*
* @param args the arguments
* @param sender the sender
* @param flag the flag (such as 'w')
* @return a world
* @throws CommandException on error
*/
protected static World checkWorld(CommandContext args, CommandSender sender, char flag) throws CommandException {
if (args.hasFlag(flag)) {
return WorldGuardPlugin.inst().matchWorld(sender, args.getFlag(flag));
} else {
if (sender instanceof Player) {
return WorldGuardPlugin.inst().checkPlayer(sender).getWorld();
} else {
throw new CommandException("Please specify " + "the world with -" + flag + " world_name.");
}
}
}
/**
* Validate a region ID.
*
* @param id the id
* @param allowGlobal whether __global__ is allowed
* @return the id given
* @throws CommandException thrown on an error
*/
protected static String checkRegionId(String id, boolean allowGlobal) throws CommandException {
if (!ProtectedRegion.isValidId(id)) {
throw new CommandException(
"The region name of '" + id + "' contains characters that are not allowed.");
}
if (!allowGlobal && id.equalsIgnoreCase("__global__")) { // Sorry, no global
throw new CommandException(
"Sorry, you can't use __global__ here.");
}
return id;
}
/**
* Get a protected region by a given name, otherwise throw a
* {@link CommandException}.
*
* <p>This also validates the region ID.</p>
*
* @param regionManager the region manager
* @param id the name to search
* @param allowGlobal true to allow selecting __global__
* @throws CommandException thrown if no region is found by the given name
*/
protected static ProtectedRegion checkExistingRegion(RegionManager regionManager, String id, boolean allowGlobal) throws CommandException {
// Validate the id
checkRegionId(id, allowGlobal);
ProtectedRegion region = regionManager.getRegion(id);
// No region found!
if (region == null) {
// But we want a __global__, so let's create one
if (id.equalsIgnoreCase("__global__")) {
region = new GlobalProtectedRegion(id);
regionManager.addRegion(region);
return region;
}
throw new CommandException(
"No region could be found with the name of '" + id + "'.");
}
return region;
}
/**
* Get the region at the player's location, if possible.
*
* <p>If the player is standing in several regions, an error will be raised
* and a list of regions will be provided.</p>
*
* @param regionManager the region manager
* @param player the player
* @return a region
* @throws CommandException thrown if no region was found
*/
protected static ProtectedRegion checkRegionStandingIn(RegionManager regionManager, Player player) throws CommandException {
return checkRegionStandingIn(regionManager, player, false);
}
/**
* Get the region at the player's location, if possible.
*
* <p>If the player is standing in several regions, an error will be raised
* and a list of regions will be provided.</p>
*
* <p>If the player is not standing in any regions, the global region will
* returned if allowGlobal is true and it exists.</p>
*
* @param regionManager the region manager
* @param player the player
* @param allowGlobal whether to search for a global region if no others are found
* @return a region
* @throws CommandException thrown if no region was found
*/
protected static ProtectedRegion checkRegionStandingIn(RegionManager regionManager, Player player, boolean allowGlobal) throws CommandException {
ApplicableRegionSet set = regionManager.getApplicableRegions(player.getLocation());
if (set.size() == 0) {
if (allowGlobal) {
ProtectedRegion global = checkExistingRegion(regionManager, "__global__", true);
player.sendMessage(ChatColor.GRAY + "You're not standing in any " +
"regions. Using the global region for this world instead.");
return global;
}
throw new CommandException(
"You're not standing in a region." +
"Specify an ID if you want to select a specific region.");
} else if (set.size() > 1) {
StringBuilder builder = new StringBuilder();
boolean first = true;
for (ProtectedRegion region : set) {
if (!first) {
builder.append(", ");
}
first = false;
builder.append(region.getId());
}
throw new CommandException(
"You're standing in several regions (please pick one).\nYou're in: " + builder.toString());
}
return set.iterator().next();
}
/**
* Get a WorldEdit selection for a player, or emit an exception if there is none
* available.
*
* @param player the player
* @return the selection
* @throws CommandException thrown on an error
*/
protected static Selection checkSelection(Player player) throws CommandException {
WorldEditPlugin worldEdit = WorldGuardPlugin.inst().getWorldEdit();
Selection selection = worldEdit.getSelection(player);
if (selection == null) {
throw new CommandException(
"Please select an area first. " +
"Use WorldEdit to make a selection! " +
"(wiki: http://wiki.sk89q.com/wiki/WorldEdit).");
}
return selection;
}
/**
* Check that a region with the given ID does not already exist.
*
* @param manager the manager
* @param id the ID
* @throws CommandException thrown if the ID already exists
*/
protected static void checkRegionDoesNotExist(RegionManager manager, String id, boolean mayRedefine) throws CommandException {
if (manager.hasRegion(id)) {
throw new CommandException("A region with that name already exists. Please choose another name." +
(mayRedefine ? " To change the shape, use /region redefine " + id + "." : ""));
}
}
/**
* Check that the given region manager is not null.
*
* @param plugin the plugin
* @param world the world
* @throws CommandException thrown if the manager is null
*/
protected static RegionManager checkRegionManager(WorldGuardPlugin plugin, World world) throws CommandException {
if (!plugin.getGlobalStateManager().get(world).useRegions) {
throw new CommandException("Region support is disabled in the target world. " +
"It can be enabled per-world in WorldGuard's configuration files. " +
"However, you may need to restart your server afterwards.");
}
RegionManager manager = plugin.getRegionContainer().get(world);
if (manager == null) {
throw new CommandException("Region data failed to load for this world. " +
"Please ask a server administrator to read the logs to identify the reason.");
}
return manager;
}
/**
* Create a {@link ProtectedRegion} from the player's selection.
*
* @param player the player
* @param id the ID of the new region
* @return a new region
* @throws CommandException thrown on an error
*/
protected static ProtectedRegion checkRegionFromSelection(Player player, String id) throws CommandException {
Selection selection = checkSelection(player);
// Detect the type of region from WorldEdit
if (selection instanceof Polygonal2DSelection) {
Polygonal2DSelection polySel = (Polygonal2DSelection) selection;
int minY = polySel.getNativeMinimumPoint().getBlockY();
int maxY = polySel.getNativeMaximumPoint().getBlockY();
return new ProtectedPolygonalRegion(id, polySel.getNativePoints(), minY, maxY);
} else if (selection instanceof CuboidSelection) {
BlockVector min = selection.getNativeMinimumPoint().toBlockVector();
BlockVector max = selection.getNativeMaximumPoint().toBlockVector();
return new ProtectedCuboidRegion(id, min, max);
} else {
throw new CommandException("Sorry, you can only use cuboids and polygons for WorldGuard regions.");
}
}
/**
* Warn the region saving is failing.
*
* @param sender the sender to send the message to
*/
protected static void warnAboutSaveFailures(CommandSender sender) {
RegionContainer container = WorldGuardPlugin.inst().getRegionContainer();
Set<RegionManager> failures = container.getSaveFailures();
if (failures.size() > 0) {
String failingList = Joiner.on(", ").join(Iterables.transform(failures, new Function<RegionManager, String>() {
@Override
public String apply(RegionManager regionManager) {
return "'" + regionManager.getName() + "'";
}
}));
sender.sendMessage(ChatColor.GOLD +
"(Warning: The background saving of region data is failing for these worlds: " + failingList + ". " +
"Your changes are getting lost. See the server log for more information.)");
}
}
/**
* Warn the sender if the dimensions of the given region are worrying.
*
* @param sender the sender to send the message to
* @param region the region
*/
protected static void warnAboutDimensions(CommandSender sender, ProtectedRegion region) {
int height = region.getMaximumPoint().getBlockY() - region.getMinimumPoint().getBlockY();
if (height <= 2) {
sender.sendMessage(ChatColor.GRAY + "(Warning: The height of the region was " + (height + 1) + " block(s).)");
}
}
/**
* Inform a new user about automatic protection.
*
* @param sender the sender to send the message to
* @param manager the region manager
* @param region the region
*/
protected static void informNewUser(CommandSender sender, RegionManager manager, ProtectedRegion region) {
if (manager.getRegions().size() <= 2) {
sender.sendMessage(ChatColor.GRAY +
"(This region is NOW PROTECTED from modification from others. " +
"Don't want that? Use " +
ChatColor.AQUA + "/rg flag " + region.getId() + " passthrough allow" +
ChatColor.GRAY + ")");
}
}
/**
* Set a player's selection to a given region.
*
* @param player the player
* @param region the region
* @throws CommandException thrown on a command error
*/
protected static void setPlayerSelection(Player player, ProtectedRegion region) throws CommandException {
WorldEditPlugin worldEdit = WorldGuardPlugin.inst().getWorldEdit();
World world = player.getWorld();
// Set selection
if (region instanceof ProtectedCuboidRegion) {
ProtectedCuboidRegion cuboid = (ProtectedCuboidRegion) region;
Vector pt1 = cuboid.getMinimumPoint();
Vector pt2 = cuboid.getMaximumPoint();
CuboidSelection selection = new CuboidSelection(world, pt1, pt2);
worldEdit.setSelection(player, selection);
player.sendMessage(ChatColor.YELLOW + "Region selected as a cuboid.");
} else if (region instanceof ProtectedPolygonalRegion) {
ProtectedPolygonalRegion poly2d = (ProtectedPolygonalRegion) region;
Polygonal2DSelection selection = new Polygonal2DSelection(
world, poly2d.getPoints(),
poly2d.getMinimumPoint().getBlockY(),
poly2d.getMaximumPoint().getBlockY() );
worldEdit.setSelection(player, selection);
player.sendMessage(ChatColor.YELLOW + "Region selected as a polygon.");
} else if (region instanceof GlobalProtectedRegion) {
throw new CommandException(
"Can't select global regions! " +
"That would cover the entire world.");
} else {
throw new CommandException("Unknown region type: " +
region.getClass().getCanonicalName());
}
}
/**
* Utility method to set a flag.
*
* @param region the region
* @param flag the flag
* @param sender the sender
* @param value the value
* @throws InvalidFlagFormat thrown if the value is invalid
*/
protected static <V> void setFlag(ProtectedRegion region, Flag<V> flag, CommandSender sender, String value) throws InvalidFlagFormat {
region.setFlag(flag, flag.parseInput(WorldGuardPlugin.inst(), sender, value));
}
}

View File

@ -17,38 +17,44 @@
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package com.sk89q.worldguard.bukkit.commands;
import java.util.ArrayList;
import java.util.List;
import java.util.ListIterator;
import org.bukkit.ChatColor;
import org.bukkit.command.CommandSender;
package com.sk89q.worldguard.bukkit.commands.region;
import com.sk89q.squirrelid.cache.ProfileCache;
import com.sk89q.worldedit.BlockVector;
import com.sk89q.worldguard.domains.DefaultDomain;
import com.sk89q.worldguard.protection.flags.DefaultFlag;
import com.sk89q.worldguard.protection.flags.Flag;
import com.sk89q.worldguard.protection.flags.RegionGroupFlag;
import com.sk89q.worldguard.protection.regions.ProtectedRegion;
import org.bukkit.ChatColor;
import org.bukkit.command.CommandSender;
import javax.annotation.Nullable;
import java.util.ArrayList;
import java.util.List;
import java.util.ListIterator;
import java.util.concurrent.Callable;
/**
* Create a region printout, as used in /region info to show information about
* a region.
*/
public class RegionPrintoutBuilder {
public class RegionPrintoutBuilder implements Callable<String> {
private final ProtectedRegion region;
@Nullable
private final ProfileCache cache;
private final StringBuilder builder = new StringBuilder();
/**
* Create a new instance with a region to report on.
*
*
* @param region the region
* @param cache a profile cache, or {@code null}
*/
public RegionPrintoutBuilder(ProtectedRegion region) {
public RegionPrintoutBuilder(ProtectedRegion region, @Nullable ProfileCache cache) {
this.region = region;
this.cache = cache;
}
/**
@ -69,7 +75,7 @@ public void appendBasics() {
builder.append(ChatColor.GRAY);
builder.append(" (type=");
builder.append(region.getTypeName());
builder.append(region.getType().getName());
builder.append(ChatColor.GRAY);
builder.append(", priority=");
@ -120,13 +126,13 @@ public void appendFlagsList(boolean useColors) {
group = region.getFlag(groupFlag);
}
if(group == null) {
if (group == null) {
builder.append(flag.getName()).append(": ")
.append(String.valueOf(val));
.append(ChatColor.stripColor(String.valueOf(val)));
} else {
builder.append(flag.getName()).append(" -g ")
.append(String.valueOf(group)).append(": ")
.append(String.valueOf(val));
.append(group).append(": ")
.append(ChatColor.stripColor(String.valueOf(val)));
}
hasFlags = true;
@ -192,7 +198,7 @@ public void appendParentTree(boolean useColors) {
if (useColors) {
builder.append(ChatColor.GRAY);
}
builder.append(" (parent, priority=" + cur.getPriority() + ")");
builder.append(" (parent, priority=").append(cur.getPriority()).append(")");
}
indent++;
@ -206,29 +212,23 @@ public void appendParentTree(boolean useColors) {
public void appendDomain() {
builder.append(ChatColor.BLUE);
builder.append("Owners: ");
DefaultDomain owners = region.getOwners();
if (owners.size() != 0) {
builder.append(ChatColor.YELLOW);
builder.append(owners.toUserFriendlyString());
} else {
builder.append(ChatColor.RED);
builder.append("(no owners)");
}
addDomainString(region.getOwners());
newLine();
builder.append(ChatColor.BLUE);
builder.append("Members: ");
DefaultDomain members = region.getMembers();
if (members.size() != 0) {
addDomainString(region.getMembers());
newLine();
}
private void addDomainString(DefaultDomain domain) {
if (domain.size() != 0) {
builder.append(ChatColor.YELLOW);
builder.append(members.toUserFriendlyString());
builder.append(domain.toUserFriendlyString(cache));
} else {
builder.append(ChatColor.RED);
builder.append("(no members)");
builder.append("(none)");
}
newLine();
}
/**
@ -240,16 +240,13 @@ public void appendBounds() {
builder.append(ChatColor.BLUE);
builder.append("Bounds:");
builder.append(ChatColor.YELLOW);
builder.append(" (" + min.getBlockX() + "," + min.getBlockY() + "," + min.getBlockZ() + ")");
builder.append(" -> (" + max.getBlockX() + "," + max.getBlockY() + "," + max.getBlockZ() + ")");
builder.append(" (").append(min.getBlockX()).append(",").append(min.getBlockY()).append(",").append(min.getBlockZ()).append(")");
builder.append(" -> (").append(max.getBlockX()).append(",").append(max.getBlockY()).append(",").append(max.getBlockZ()).append(")");
newLine();
}
/**
* Append all the default fields used for /rg info.
*/
public void appendRegionInfo() {
private void appendRegionInformation() {
builder.append(ChatColor.GRAY);
builder.append("\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550");
builder.append(" Region Info ");
@ -260,17 +257,28 @@ public void appendRegionInfo() {
appendParents();
appendDomain();
appendBounds();
if (cache != null) {
builder.append(ChatColor.GRAY).append("Any names suffixed by * are 'last seen names' and may not be up to date.");
newLine();
}
}
@Override
public String call() throws Exception {
appendRegionInformation();
return builder.toString();
}
/**
* Send the report to a {@link CommandSender}.
*
* @param sender the recepient
*
* @param sender the recipient
*/
public void send(CommandSender sender) {
sender.sendMessage(toString());
}
public StringBuilder append(boolean b) {
return builder.append(b);
}

View File

@ -0,0 +1,108 @@
/*
* WorldGuard, a suite of tools for Minecraft
* Copyright (C) sk89q <http://www.sk89q.com>
* Copyright (C) WorldGuard team and contributors
*
* This program is free software: you can redistribute it and/or modify it
* under the terms of the GNU Lesser General Public License as published by the
* Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License
* for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package com.sk89q.worldguard.bukkit.commands.task;
import com.sk89q.minecraft.util.commands.CommandContext;
import com.sk89q.worldguard.bukkit.WorldGuardPlugin;
import com.sk89q.worldguard.domains.DefaultDomain;
import com.sk89q.worldguard.protection.managers.RegionManager;
import com.sk89q.worldguard.protection.regions.ProtectedRegion;
import com.sk89q.worldguard.protection.util.DomainInputResolver;
import com.sk89q.worldguard.protection.util.DomainInputResolver.UserLocatorPolicy;
import javax.annotation.Nullable;
import java.util.concurrent.Callable;
import static com.google.common.base.Preconditions.checkNotNull;
/**
* Creates a new region.
*/
public class RegionAdder implements Callable<ProtectedRegion> {
private final WorldGuardPlugin plugin;
private final RegionManager manager;
private final ProtectedRegion region;
@Nullable
private String[] ownersInput;
private UserLocatorPolicy locatorPolicy = UserLocatorPolicy.UUID_ONLY;
/**
* Create a new instance.
*
* @param plugin the plugin
* @param manager the manage
* @param region the region
*/
public RegionAdder(WorldGuardPlugin plugin, RegionManager manager, ProtectedRegion region) {
checkNotNull(plugin);
checkNotNull(manager);
checkNotNull(region);
this.plugin = plugin;
this.manager = manager;
this.region = region;
}
/**
* Add the owners from the command's arguments.
*
* @param args the arguments
* @param namesIndex the index in the list of arguments to read the first name from
*/
public void addOwnersFromCommand(CommandContext args, int namesIndex) {
if (args.argsLength() >= namesIndex) {
setLocatorPolicy(args.hasFlag('n') ? UserLocatorPolicy.NAME_ONLY : UserLocatorPolicy.UUID_ONLY);
setOwnersInput(args.getSlice(namesIndex));
}
}
@Override
public ProtectedRegion call() throws Exception {
if (ownersInput != null) {
DomainInputResolver resolver = new DomainInputResolver(plugin.getProfileService(), ownersInput);
resolver.setLocatorPolicy(locatorPolicy);
DefaultDomain domain = resolver.call();
region.getOwners().addAll(domain);
}
manager.addRegion(region);
return region;
}
@Nullable
public String[] getOwnersInput() {
return ownersInput;
}
public void setOwnersInput(@Nullable String[] ownersInput) {
this.ownersInput = ownersInput;
}
public UserLocatorPolicy getLocatorPolicy() {
return locatorPolicy;
}
public void setLocatorPolicy(UserLocatorPolicy locatorPolicy) {
this.locatorPolicy = locatorPolicy;
}
}

View File

@ -0,0 +1,232 @@
/*
* WorldGuard, a suite of tools for Minecraft
* Copyright (C) sk89q <http://www.sk89q.com>
* Copyright (C) WorldGuard team and contributors
*
* This program is free software: you can redistribute it and/or modify it
* under the terms of the GNU Lesser General Public License as published by the
* Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License
* for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package com.sk89q.worldguard.bukkit.commands.task;
import com.sk89q.minecraft.util.commands.CommandException;
import com.sk89q.squirrelid.Profile;
import com.sk89q.worldguard.bukkit.WorldGuardPlugin;
import com.sk89q.worldguard.domains.DefaultDomain;
import com.sk89q.worldguard.protection.managers.RegionManager;
import com.sk89q.worldguard.protection.regions.ProtectedRegion;
import org.bukkit.ChatColor;
import org.bukkit.command.CommandSender;
import org.bukkit.entity.Player;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.Map;
import java.util.UUID;
import java.util.concurrent.Callable;
import java.util.logging.Level;
import java.util.logging.Logger;
import static com.google.common.base.Preconditions.checkNotNull;
public class RegionLister implements Callable<Integer> {
private static final Logger log = Logger.getLogger(RegionLister.class.getCanonicalName());
private final WorldGuardPlugin plugin;
private final CommandSender sender;
private final RegionManager manager;
private OwnerMatcher ownerMatcher;
private int page;
public RegionLister(WorldGuardPlugin plugin, RegionManager manager, CommandSender sender) {
checkNotNull(plugin);
checkNotNull(manager);
checkNotNull(sender);
this.plugin = plugin;
this.manager = manager;
this.sender = sender;
}
public int getPage() {
return page;
}
public void setPage(int page) {
this.page = page;
}
public void filterOwnedByPlayer(final Player player) {
ownerMatcher = new OwnerMatcher() {
@Override
public String getName() {
return player.getName();
}
@Override
public boolean isContainedWithin(DefaultDomain domain) throws CommandException {
return domain.contains(player.getUniqueId());
}
};
}
public void filterOwnedByName(String name, boolean nameOnly) {
if (nameOnly) {
filterOwnedByName(name);
} else {
filterOwnedByProfile(name);
}
}
private void filterOwnedByName(final String name) {
ownerMatcher = new OwnerMatcher() {
@Override
public String getName() {
return name;
}
@Override
public boolean isContainedWithin(DefaultDomain domain) throws CommandException {
return domain.contains(name);
}
};
}
private void filterOwnedByProfile(final String name) {
ownerMatcher = new OwnerMatcher() {
private UUID uniqueId;
@Override
public String getName() {
return name;
}
@Override
public boolean isContainedWithin(DefaultDomain domain) throws CommandException {
if (uniqueId == null) {
Profile profile;
try {
profile = plugin.getProfileService().findByName(name);
} catch (IOException e) {
log.log(Level.WARNING, "Failed UUID lookup of '" + name + "'", e);
throw new CommandException("Failed to lookup the UUID of '" + name + "'");
} catch (InterruptedException e) {
log.log(Level.WARNING, "Failed UUID lookup of '" + name + "'", e);
throw new CommandException("The lookup the UUID of '" + name + "' was interrupted");
}
if (profile == null) {
throw new CommandException("A user by the name of '" + name + "' does not seem to exist.");
}
uniqueId = profile.getUniqueId();
}
return domain.contains(uniqueId);
}
};
}
@Override
public Integer call() throws Exception {
Map<String, ProtectedRegion> regions = manager.getRegions();
// Build a list of regions to show
List<RegionListEntry> entries = new ArrayList<RegionListEntry>();
int index = 0;
for (String id : regions.keySet()) {
RegionListEntry entry = new RegionListEntry(id, index++);
// Filtering by owner?
ProtectedRegion region = regions.get(id);
if (ownerMatcher != null) {
entry.isOwner = ownerMatcher.isContainedWithin(region.getOwners());
entry.isMember = ownerMatcher.isContainedWithin(region.getMembers());
if (!entry.isOwner && !entry.isMember) {
continue; // Skip
}
}
entries.add(entry);
}
Collections.sort(entries);
final int totalSize = entries.size();
final int pageSize = 10;
final int pages = (int) Math.ceil(totalSize / (float) pageSize);
sender.sendMessage(ChatColor.RED
+ (ownerMatcher == null ? "Regions (page " : "Regions for " + ownerMatcher.getName() + " (page ")
+ (page + 1) + " of " + pages + "):");
if (page < pages) {
// Print
for (int i = page * pageSize; i < page * pageSize + pageSize; i++) {
if (i >= totalSize) {
break;
}
sender.sendMessage(ChatColor.YELLOW.toString() + entries.get(i));
}
}
return page;
}
private static interface OwnerMatcher {
public String getName();
public boolean isContainedWithin(DefaultDomain domain) throws CommandException;
}
private class RegionListEntry implements Comparable<RegionListEntry> {
private final String id;
private final int index;
boolean isOwner;
boolean isMember;
private RegionListEntry(String id, int index) {
this.id = id;
this.index = index;
}
@Override
public int compareTo(RegionListEntry o) {
if (isOwner != o.isOwner) {
return isOwner ? 1 : -1;
}
if (isMember != o.isMember) {
return isMember ? 1 : -1;
}
return id.compareTo(o.id);
}
@Override
public String toString() {
if (isOwner) {
return (index + 1) + ". +" + id;
} else if (isMember) {
return (index + 1) + ". -" + id;
} else {
return (index + 1) + ". " + id;
}
}
}
}

View File

@ -0,0 +1,53 @@
/*
* WorldGuard, a suite of tools for Minecraft
* Copyright (C) sk89q <http://www.sk89q.com>
* Copyright (C) WorldGuard team and contributors
*
* This program is free software: you can redistribute it and/or modify it
* under the terms of the GNU Lesser General Public License as published by the
* Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License
* for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package com.sk89q.worldguard.bukkit.commands.task;
import com.sk89q.worldguard.protection.managers.RegionManager;
import com.sk89q.worldguard.protection.managers.storage.StorageException;
import java.util.Arrays;
import java.util.Collection;
import java.util.concurrent.Callable;
import static com.google.common.base.Preconditions.checkNotNull;
public class RegionManagerReloader implements Callable<Collection<RegionManager>> {
private final Collection<RegionManager> managers;
public RegionManagerReloader(Collection<RegionManager> managers) {
checkNotNull(managers);
this.managers = managers;
}
public RegionManagerReloader(RegionManager... manager) {
this(Arrays.asList(manager));
}
@Override
public Collection<RegionManager> call() throws StorageException {
for (RegionManager manager : managers) {
manager.load();
}
return managers;
}
}

View File

@ -0,0 +1,53 @@
/*
* WorldGuard, a suite of tools for Minecraft
* Copyright (C) sk89q <http://www.sk89q.com>
* Copyright (C) WorldGuard team and contributors
*
* This program is free software: you can redistribute it and/or modify it
* under the terms of the GNU Lesser General Public License as published by the
* Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License
* for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package com.sk89q.worldguard.bukkit.commands.task;
import com.sk89q.worldguard.protection.managers.RegionManager;
import com.sk89q.worldguard.protection.managers.storage.StorageException;
import java.util.Arrays;
import java.util.Collection;
import java.util.concurrent.Callable;
import static com.google.common.base.Preconditions.checkNotNull;
public class RegionManagerSaver implements Callable<Collection<RegionManager>> {
private final Collection<RegionManager> managers;
public RegionManagerSaver(Collection<RegionManager> managers) {
checkNotNull(managers);
this.managers = managers;
}
public RegionManagerSaver(RegionManager... manager) {
this(Arrays.asList(manager));
}
@Override
public Collection<RegionManager> call() throws StorageException {
for (RegionManager manager : managers) {
manager.save();
}
return managers;
}
}

View File

@ -0,0 +1,93 @@
/*
* WorldGuard, a suite of tools for Minecraft
* Copyright (C) sk89q <http://www.sk89q.com>
* Copyright (C) WorldGuard team and contributors
*
* This program is free software: you can redistribute it and/or modify it
* under the terms of the GNU Lesser General Public License as published by the
* Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License
* for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package com.sk89q.worldguard.bukkit.commands.task;
import com.sk89q.minecraft.util.commands.CommandException;
import com.sk89q.worldguard.protection.managers.RegionManager;
import com.sk89q.worldguard.protection.managers.RemovalStrategy;
import com.sk89q.worldguard.protection.regions.ProtectedRegion;
import javax.annotation.Nullable;
import java.util.Set;
import java.util.concurrent.Callable;
import static com.google.common.base.Preconditions.checkNotNull;
/**
* Removes a region.
*/
public class RegionRemover implements Callable<Set<ProtectedRegion>> {
private final RegionManager manager;
private final ProtectedRegion region;
@Nullable
private RemovalStrategy removalStrategy;
/**
* Create a new instance.
*
* @param manager a region manager
* @param region the region to remove
*/
public RegionRemover(RegionManager manager, ProtectedRegion region) {
checkNotNull(manager);
checkNotNull(region);
this.manager = manager;
this.region = region;
}
/**
* GSet a parent removal strategy.
*
* @return a removal strategy or null (see{@link #setRemovalStrategy(RemovalStrategy)}
*/
@Nullable
public RemovalStrategy getRemovalStrategy() {
return removalStrategy;
}
/**
* Set a parent removal strategy. Set it to {@code null} to have the code
* check for children and throw an error if any are found.
*
* @param removalStrategy a removal strategy, or {@code null} to error if children exist
*/
public void setRemovalStrategy(@Nullable RemovalStrategy removalStrategy) {
this.removalStrategy = removalStrategy;
}
@Override
public Set<ProtectedRegion> call() throws Exception {
if (removalStrategy == null) {
for (ProtectedRegion test : manager.getRegions().values()) {
ProtectedRegion parent = test.getParent();
if (parent != null && parent.equals(region)) {
throw new CommandException(
"The region '" + region.getId() + "' has child regions. Use -f to force removal of children " +
"or -u to unset the parent value of these children.");
}
}
return manager.removeRegion(region.getId(), RemovalStrategy.UNSET_PARENT_IN_CHILDREN);
} else {
return manager.removeRegion(region.getId(), removalStrategy);
}
}
}

View File

@ -17,66 +17,52 @@
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package com.sk89q.worldguard.internal.event;
package com.sk89q.worldguard.bukkit.event;
import com.sk89q.worldguard.internal.cause.Cause;
import com.sk89q.worldguard.bukkit.cause.Cause;
import org.bukkit.event.Cancellable;
import org.bukkit.event.Event;
import java.util.Collections;
import java.util.List;
import javax.annotation.Nullable;
import static com.google.common.base.Preconditions.checkNotNull;
abstract class AbstractInteractEvent extends Event implements Cancellable {
public abstract class AbstractDelegateEvent extends Event implements Cancellable {
@Nullable
private final Event originalEvent;
private final List<? extends Cause<?>> causes;
private final Interaction interaction;
private final Cause cause;
private boolean cancelled;
/**
* Create a new instance
*
* @param originalEvent the original event
* @param causes a list of causes, where the originating causes are at the beginning
* @param interaction the action that is being taken
* @param cause the cause
*/
protected AbstractInteractEvent(Event originalEvent, List<? extends Cause<?>> causes, Interaction interaction) {
checkNotNull(originalEvent);
checkNotNull(causes);
checkNotNull(interaction);
protected AbstractDelegateEvent(@Nullable Event originalEvent, Cause cause) {
checkNotNull(cause);
this.originalEvent = originalEvent;
this.causes = causes;
this.interaction = interaction;
this.cause = cause;
}
/**
* Get the original event.
*
* @return the original event
* @return the original event, which may be {@code null} if unavailable
*/
@Nullable
public Event getOriginalEvent() {
return originalEvent;
}
/**
* Return an unmodifiable list of causes, where the originating causes are
* at the beginning of the list.
* Return the cause.
*
* @return a list of causes
* @return the cause
*/
public List<? extends Cause<?>> getCauses() {
return Collections.unmodifiableList(causes);
}
/**
* Get the action that is being taken.
*
* @return the action
*/
public Interaction getInteraction() {
return interaction;
public Cause getCause() {
return cause;
}
@Override

View File

@ -0,0 +1,38 @@
/*
* 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;
/**
* A bulk event contains several affected objects in a list.
*/
public interface BulkEvent {
/**
* Return whether the event is explicitly cancelled.
*
* <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>
*
* @return true if really cancelled
*/
boolean isExplicitlyCancelled();
}

View File

@ -0,0 +1,153 @@
/*
* 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.block;
import com.google.common.base.Predicate;
import com.sk89q.worldguard.bukkit.cause.Cause;
import com.sk89q.worldguard.bukkit.event.AbstractDelegateEvent;
import com.sk89q.worldguard.bukkit.event.BulkEvent;
import org.bukkit.Location;
import org.bukkit.Material;
import org.bukkit.World;
import org.bukkit.block.Block;
import org.bukkit.event.Event;
import javax.annotation.Nullable;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
import static com.google.common.base.Preconditions.checkNotNull;
abstract class AbstractBlockEvent extends AbstractDelegateEvent implements BulkEvent {
private final World world;
private final List<Block> blocks;
private final Material effectiveMaterial;
protected AbstractBlockEvent(@Nullable Event originalEvent, Cause cause, World world, List<Block> blocks, Material effectiveMaterial) {
super(originalEvent, cause);
checkNotNull(world);
checkNotNull(blocks);
checkNotNull(effectiveMaterial);
this.world = world;
this.blocks = blocks;
this.effectiveMaterial = effectiveMaterial;
}
protected AbstractBlockEvent(@Nullable Event originalEvent, Cause cause, Block block) {
this(originalEvent, cause, block.getWorld(), createList(checkNotNull(block)), block.getType());
}
protected AbstractBlockEvent(@Nullable Event originalEvent, Cause cause, Location target, Material effectiveMaterial) {
this(originalEvent, cause, target.getWorld(), createList(target.getBlock()), effectiveMaterial);
}
private static List<Block> createList(Block block) {
List<Block> blocks = new ArrayList<Block>();
blocks.add(block);
return blocks;
}
@Override
public boolean isCancelled() {
return super.isCancelled() || blocks.isEmpty();
}
@Override
public boolean isExplicitlyCancelled() {
return super.isCancelled();
}
/**
* Get the world.
*
* @return the world
*/
public World getWorld() {
return world;
}
/**
* Get the affected blocks.
*
* @return a list of affected block
*/
public List<Block> getBlocks() {
return blocks;
}
/**
* Filter the list of affected blocks with the given predicate. If the
* predicate returns {@code false}, then the block is removed.
*
* @param predicate the predicate
* @param cancelEventOnFalse true to cancel the event and clear the block
* list once the predicate returns {@code false}
* @return true if one or more blocks were filtered out
*/
public boolean filter(Predicate<Location> predicate, boolean cancelEventOnFalse) {
boolean hasRemoval = false;
Iterator<Block> it = blocks.iterator();
while (it.hasNext()) {
if (!predicate.apply(it.next().getLocation())) {
hasRemoval = true;
if (cancelEventOnFalse) {
getBlocks().clear();
setCancelled(true);
break;
} else {
it.remove();
}
}
}
return hasRemoval;
}
/**
* Filter the list of affected blocks with the given predicate. If the
* predicate returns {@code false}, then the block is removed.
*
* <p>This method will <strong>not</strong> fail fast and
* cancel the event the first instance that the predicate returns
* {@code false}. See {@link #filter(Predicate, boolean)} to adjust
* this behavior.</p>
*
* @param predicate the predicate
* @return true if one or more blocks were filtered out
*/
public boolean filter(Predicate<Location> predicate) {
return filter(predicate, false);
}
/**
* Get the effective material of the block, regardless of what the block
* currently is.
*
* @return the effective material
*/
public Material getEffectiveMaterial() {
return effectiveMaterial;
}
}

View File

@ -0,0 +1,58 @@
/*
* 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.block;
import com.sk89q.worldguard.bukkit.cause.Cause;
import org.bukkit.Location;
import org.bukkit.Material;
import org.bukkit.World;
import org.bukkit.block.Block;
import org.bukkit.event.Event;
import org.bukkit.event.HandlerList;
import javax.annotation.Nullable;
import java.util.List;
public class BreakBlockEvent extends AbstractBlockEvent {
private static final HandlerList handlers = new HandlerList();
public BreakBlockEvent(@Nullable Event originalEvent, Cause cause, World world, List<Block> blocks, Material effectiveMaterial) {
super(originalEvent, cause, world, blocks, effectiveMaterial);
}
public BreakBlockEvent(@Nullable Event originalEvent, Cause cause, Block block) {
super(originalEvent, cause, block);
}
public BreakBlockEvent(@Nullable Event originalEvent, Cause cause, Location target, Material effectiveMaterial) {
super(originalEvent, cause, target, effectiveMaterial);
}
@Override
public HandlerList getHandlers() {
return handlers;
}
public static HandlerList getHandlerList() {
return handlers;
}
}

View File

@ -0,0 +1,58 @@
/*
* 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.block;
import com.sk89q.worldguard.bukkit.cause.Cause;
import org.bukkit.Location;
import org.bukkit.Material;
import org.bukkit.World;
import org.bukkit.block.Block;
import org.bukkit.event.Event;
import org.bukkit.event.HandlerList;
import javax.annotation.Nullable;
import java.util.List;
public class PlaceBlockEvent extends AbstractBlockEvent {
private static final HandlerList handlers = new HandlerList();
public PlaceBlockEvent(@Nullable Event originalEvent, Cause cause, World world, List<Block> blocks, Material effectiveMaterial) {
super(originalEvent, cause, world, blocks, effectiveMaterial);
}
public PlaceBlockEvent(@Nullable Event originalEvent, Cause cause, Block block) {
super(originalEvent, cause, block);
}
public PlaceBlockEvent(@Nullable Event originalEvent, Cause cause, Location target, Material effectiveMaterial) {
super(originalEvent, cause, target, effectiveMaterial);
}
@Override
public HandlerList getHandlers() {
return handlers;
}
public static HandlerList getHandlerList() {
return handlers;
}
}

View File

@ -17,46 +17,36 @@
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package com.sk89q.worldguard.internal.event;
package com.sk89q.worldguard.bukkit.event.block;
import com.sk89q.worldguard.internal.cause.Cause;
import com.sk89q.worldguard.bukkit.cause.Cause;
import org.bukkit.Location;
import org.bukkit.Material;
import org.bukkit.World;
import org.bukkit.block.Block;
import org.bukkit.event.Event;
import org.bukkit.event.HandlerList;
import javax.annotation.Nullable;
import java.util.List;
import static com.google.common.base.Preconditions.checkNotNull;
/**
* Fired when a block is interacted with.
*/
public class BlockInteractEvent extends AbstractInteractEvent {
public class UseBlockEvent extends AbstractBlockEvent {
private static final HandlerList handlers = new HandlerList();
private final Block target;
/**
* Create a new instance.
*
* @param originalEvent the original event
* @param causes a list of causes, where the originating causes are at the beginning
* @param interaction the action that is being taken
* @param target the target block being affected
*/
public BlockInteractEvent(Event originalEvent, List<? extends Cause<?>> causes, Interaction interaction, Block target) {
super(originalEvent, causes, interaction);
checkNotNull(target);
this.target = target;
public UseBlockEvent(@Nullable Event originalEvent, Cause cause, World world, List<Block> blocks, Material effectiveMaterial) {
super(originalEvent, cause, world, blocks, effectiveMaterial);
}
/**
* Get the target block being affected.
*
* @return a block
*/
public Block getTarget() {
return target;
public UseBlockEvent(@Nullable Event originalEvent, Cause cause, Block block) {
super(originalEvent, cause, block);
}
public UseBlockEvent(@Nullable Event originalEvent, Cause cause, Location target, Material effectiveMaterial) {
super(originalEvent, cause, target, effectiveMaterial);
}
@Override

View File

@ -0,0 +1,102 @@
/*
* 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.entity;
import com.google.common.base.Predicate;
import com.sk89q.worldguard.bukkit.cause.Cause;
import com.sk89q.worldguard.bukkit.event.AbstractDelegateEvent;
import org.bukkit.Location;
import org.bukkit.World;
import org.bukkit.entity.Entity;
import org.bukkit.event.Event;
import javax.annotation.Nullable;
import static com.google.common.base.Preconditions.checkNotNull;
abstract class AbstractEntityEvent extends AbstractDelegateEvent {
private final Location target;
@Nullable
private final Entity entity;
protected AbstractEntityEvent(@Nullable Event originalEvent, Cause cause, Entity entity) {
super(originalEvent, cause);
checkNotNull(entity);
this.target = entity.getLocation();
this.entity = entity;
}
protected AbstractEntityEvent(@Nullable Event originalEvent, Cause cause, Location target) {
super(originalEvent, cause);
checkNotNull(target);
this.target = target;
this.entity = null;
}
/**
* Get the world.
*
* @return the world
*/
public World getWorld() {
return target.getWorld();
}
/**
* Get the target location being affected.
*
* @return a location
*/
public Location getTarget() {
return target;
}
/**
* Get the target entity being affected.
*
* @return a entity
*/
@Nullable
public Entity getEntity() {
return entity;
}
/**
* Filter the list of affected entities with the given predicate. If the
* predicate returns {@code false}, then the entity is not affected.
*
* @param predicate the predicate
* @param cancelEventOnFalse true to cancel the event and clear the entity
* list once the predicate returns {@code false}
* @return true if one or more entities were filtered out
*/
public boolean filter(Predicate<Location> predicate, boolean cancelEventOnFalse) {
if (!isCancelled()) {
if (!predicate.apply(getTarget())) {
setCancelled(true);
}
}
return isCancelled();
}
}

View File

@ -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.bukkit.event.entity;
import com.sk89q.worldguard.bukkit.cause.Cause;
import org.bukkit.entity.Entity;
import org.bukkit.event.Event;
import org.bukkit.event.HandlerList;
import javax.annotation.Nonnull;
import javax.annotation.Nullable;
import static com.google.common.base.Preconditions.checkNotNull;
public class DamageEntityEvent extends AbstractEntityEvent {
private static final HandlerList handlers = new HandlerList();
public DamageEntityEvent(@Nullable Event originalEvent, Cause cause, Entity target) {
super(originalEvent, cause, checkNotNull(target));
}
@Override
@Nonnull
public Entity getEntity() {
return super.getEntity();
}
@Override
public HandlerList getHandlers() {
return handlers;
}
public static HandlerList getHandlerList() {
return handlers;
}
}

View File

@ -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.bukkit.event.entity;
import com.sk89q.worldguard.bukkit.cause.Cause;
import org.bukkit.entity.Entity;
import org.bukkit.event.Event;
import org.bukkit.event.HandlerList;
import javax.annotation.Nonnull;
import javax.annotation.Nullable;
import static com.google.common.base.Preconditions.checkNotNull;
public class DestroyEntityEvent extends AbstractEntityEvent {
private static final HandlerList handlers = new HandlerList();
public DestroyEntityEvent(@Nullable Event originalEvent, Cause cause, Entity target) {
super(originalEvent, cause, checkNotNull(target));
}
@Override
@Nonnull
public Entity getEntity() {
return super.getEntity();
}
@Override
public HandlerList getHandlers() {
return handlers;
}
public static HandlerList getHandlerList() {
return handlers;
}
}

View File

@ -0,0 +1,67 @@
/*
* 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.entity;
import com.sk89q.worldguard.bukkit.cause.Cause;
import org.bukkit.Location;
import org.bukkit.entity.Entity;
import org.bukkit.entity.EntityType;
import org.bukkit.event.Event;
import org.bukkit.event.HandlerList;
import javax.annotation.Nullable;
import static com.google.common.base.Preconditions.checkNotNull;
public class SpawnEntityEvent extends AbstractEntityEvent {
private static final HandlerList handlers = new HandlerList();
private final EntityType effectiveType;
public SpawnEntityEvent(@Nullable Event originalEvent, Cause cause, Entity target) {
super(originalEvent, cause, checkNotNull(target));
this.effectiveType = target.getType();
}
public SpawnEntityEvent(@Nullable Event originalEvent, Cause cause, Location location, EntityType type) {
super(originalEvent, cause, location);
checkNotNull(type);
this.effectiveType = type;
}
/**
* Get the effective entity type of the spawned entity.
*
* @return the effective type
*/
public EntityType getEffectiveType() {
return effectiveType;
}
@Override
public HandlerList getHandlers() {
return handlers;
}
public static HandlerList getHandlerList() {
return handlers;
}
}

View File

@ -17,46 +17,33 @@
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package com.sk89q.worldguard.internal.event;
package com.sk89q.worldguard.bukkit.event.entity;
import com.sk89q.worldguard.internal.cause.Cause;
import com.sk89q.worldguard.bukkit.cause.Cause;
import org.bukkit.entity.Entity;
import org.bukkit.event.Event;
import org.bukkit.event.HandlerList;
import java.util.List;
import javax.annotation.Nonnull;
import javax.annotation.Nullable;
import static com.google.common.base.Preconditions.checkNotNull;
/**
* Fired when an entity is interacted with.
*/
public class EntityInteractEvent extends AbstractInteractEvent {
public class UseEntityEvent extends AbstractEntityEvent {
private static final HandlerList handlers = new HandlerList();
private final Entity target;
/**
* Create a new instance.
*
* @param originalEvent the original event
* @param causes a list of causes, where the originating causes are at the beginning
* @param interaction the action that is being taken
* @param target the target entity being affected
*/
public EntityInteractEvent(Event originalEvent, List<? extends Cause<?>> causes, Interaction interaction, Entity target) {
super(originalEvent, causes, interaction);
checkNotNull(target);
this.target = target;
public UseEntityEvent(@Nullable Event originalEvent, Cause cause, Entity target) {
super(originalEvent, cause, checkNotNull(target));
}
/**
* Get the target entity.
*
* @return the target entity
*/
public Entity getTarget() {
return target;
@Override
@Nonnull
public Entity getEntity() {
return super.getEntity();
}
@Override
@ -67,4 +54,5 @@ public HandlerList getHandlers() {
public static HandlerList getHandlerList() {
return handlers;
}
}

View File

@ -17,38 +17,30 @@
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package com.sk89q.worldguard.internal.event;
package com.sk89q.worldguard.bukkit.event.inventory;
import com.sk89q.worldguard.internal.cause.Cause;
import com.sk89q.worldguard.bukkit.cause.Cause;
import com.sk89q.worldguard.bukkit.event.AbstractDelegateEvent;
import org.bukkit.World;
import org.bukkit.event.Event;
import org.bukkit.event.HandlerList;
import org.bukkit.inventory.ItemStack;
import java.util.List;
import javax.annotation.Nullable;
import static com.google.common.base.Preconditions.checkNotNull;
/**
* Fired when an item is interacted with.
*/
public class ItemInteractEvent extends AbstractInteractEvent {
public class UseItemEvent extends AbstractDelegateEvent {
private static final HandlerList handlers = new HandlerList();
private final World world;
private final ItemStack itemStack;
/**
* Create a new instance.
*
* @param originalEvent the original event
* @param causes a list of causes, where the originating causes are at the beginning
* @param interaction the action that is being taken
* @param world the world
* @param itemStack the item
*/
public ItemInteractEvent(Event originalEvent, List<? extends Cause<?>> causes, Interaction interaction, World world, ItemStack itemStack) {
super(originalEvent, causes, interaction);
public UseItemEvent(@Nullable Event originalEvent, Cause cause, World world, ItemStack itemStack) {
super(originalEvent, cause);
checkNotNull(world);
checkNotNull(itemStack);
this.world = world;

View File

@ -17,8 +17,9 @@
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package com.sk89q.worldguard.internal.listener;
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 org.bukkit.World;
@ -60,6 +61,15 @@ protected WorldGuardPlugin getPlugin() {
return plugin;
}
/**
* Get the global configuration.
*
* @return the configuration
*/
protected ConfigurationManager getConfig() {
return plugin.getGlobalStateManager();
}
/**
* Get the world configuration given a world.
*
@ -80,4 +90,14 @@ protected WorldConfiguration getWorldConfig(Player player) {
return getWorldConfig(player.getWorld());
}
/**
* Return whether region support is enabled.
*
* @param world the world
* @return true if region support is enabled
*/
protected boolean isRegionSupportEnabled(World world) {
return getWorldConfig(world).useRegions;
}
}

View File

@ -0,0 +1,262 @@
/*
* 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.google.common.base.Predicate;
import com.sk89q.worldguard.LocalPlayer;
import com.sk89q.worldguard.blacklist.event.BlockBreakBlacklistEvent;
import com.sk89q.worldguard.blacklist.event.BlockDispenseBlacklistEvent;
import com.sk89q.worldguard.blacklist.event.BlockInteractBlacklistEvent;
import com.sk89q.worldguard.blacklist.event.BlockPlaceBlacklistEvent;
import com.sk89q.worldguard.blacklist.event.ItemAcquireBlacklistEvent;
import com.sk89q.worldguard.blacklist.event.ItemDestroyWithBlacklistEvent;
import com.sk89q.worldguard.blacklist.event.ItemDropBlacklistEvent;
import com.sk89q.worldguard.blacklist.event.ItemUseBlacklistEvent;
import com.sk89q.worldguard.bukkit.ConfigurationManager;
import com.sk89q.worldguard.bukkit.WorldConfiguration;
import com.sk89q.worldguard.bukkit.WorldGuardPlugin;
import com.sk89q.worldguard.bukkit.event.block.BreakBlockEvent;
import com.sk89q.worldguard.bukkit.event.block.PlaceBlockEvent;
import com.sk89q.worldguard.bukkit.event.block.UseBlockEvent;
import com.sk89q.worldguard.bukkit.event.entity.DestroyEntityEvent;
import com.sk89q.worldguard.bukkit.event.entity.SpawnEntityEvent;
import com.sk89q.worldguard.bukkit.event.inventory.UseItemEvent;
import com.sk89q.worldguard.bukkit.util.Materials;
import org.bukkit.Location;
import org.bukkit.Material;
import org.bukkit.entity.Entity;
import org.bukkit.entity.Item;
import org.bukkit.entity.Player;
import org.bukkit.event.EventHandler;
import org.bukkit.event.block.BlockDispenseEvent;
import org.bukkit.event.player.PlayerDropItemEvent;
import org.bukkit.inventory.ItemStack;
import static com.sk89q.worldguard.bukkit.BukkitUtil.createTarget;
import static com.sk89q.worldguard.bukkit.BukkitUtil.toVector;
/**
* Handle events that need to be processed by the blacklist.
*/
public class BlacklistListener extends AbstractListener {
/**
* Construct the listener.
*
* @param plugin an instance of WorldGuardPlugin
*/
public BlacklistListener(WorldGuardPlugin plugin) {
super(plugin);
}
@EventHandler(ignoreCancelled = true)
public void onBreakBlock(final BreakBlockEvent event) {
final Player player = event.getCause().getFirstPlayer();
if (player == null) {
return;
}
final LocalPlayer localPlayer = getPlugin().wrapPlayer(player);
final WorldConfiguration wcfg = getWorldConfig(player);
// Blacklist guard
if (wcfg.getBlacklist() == null) {
return;
}
event.filter(new Predicate<Location>() {
@Override
public boolean apply(Location target) {
if (!wcfg.getBlacklist().check(
new BlockBreakBlacklistEvent(localPlayer, toVector(target), createTarget(target.getBlock(), event.getEffectiveMaterial())), false, false)) {
return false;
} else if (!wcfg.getBlacklist().check(
new ItemDestroyWithBlacklistEvent(localPlayer, toVector(target), createTarget(player.getItemInHand())), false, false)) {
return false;
}
return true;
}
});
}
@EventHandler(ignoreCancelled = true)
public void onPlaceBlock(final PlaceBlockEvent event) {
Player player = event.getCause().getFirstPlayer();
if (player == null) {
return;
}
final LocalPlayer localPlayer = getPlugin().wrapPlayer(player);
final WorldConfiguration wcfg = getWorldConfig(player);
// Blacklist guard
if (wcfg.getBlacklist() == null) {
return;
}
event.filter(new Predicate<Location>() {
@Override
public boolean apply(Location target) {
return wcfg.getBlacklist().check(new BlockPlaceBlacklistEvent(
localPlayer, toVector(target), createTarget(target.getBlock(), event.getEffectiveMaterial())), false, false);
}
});
}
@EventHandler(ignoreCancelled = true)
public void onUseBlock(final UseBlockEvent event) {
Player player = event.getCause().getFirstPlayer();
if (player == null) {
return;
}
final LocalPlayer localPlayer = getPlugin().wrapPlayer(player);
final WorldConfiguration wcfg = getWorldConfig(player);
// Blacklist guard
if (wcfg.getBlacklist() == null) {
return;
}
event.filter(new Predicate<Location>() {
@Override
public boolean apply(Location target) {
return wcfg.getBlacklist().check(new BlockInteractBlacklistEvent(
localPlayer, toVector(target), createTarget(target.getBlock(), event.getEffectiveMaterial())), false, false);
}
});
}
@EventHandler(ignoreCancelled = true)
public void onSpawnEntity(SpawnEntityEvent event) {
Player player = event.getCause().getFirstPlayer();
if (player == null) {
return;
}
LocalPlayer localPlayer = getPlugin().wrapPlayer(player);
WorldConfiguration wcfg = getWorldConfig(player);
// Blacklist guard
if (wcfg.getBlacklist() == null) {
return;
}
Material material = Materials.getRelatedMaterial(event.getEffectiveType());
if (material != null) {
if (!wcfg.getBlacklist().check(new ItemUseBlacklistEvent(localPlayer, toVector(event.getTarget()), createTarget(material)), false, false)) {
event.setCancelled(true);
}
}
}
@EventHandler(ignoreCancelled = true)
public void onDestroyEntity(DestroyEntityEvent event) {
Player player = event.getCause().getFirstPlayer();
if (player == null) {
return;
}
LocalPlayer localPlayer = getPlugin().wrapPlayer(player);
Entity target = event.getEntity();
WorldConfiguration wcfg = getWorldConfig(player);
// Blacklist guard
if (wcfg.getBlacklist() == null) {
return;
}
if (target instanceof Item) {
Item item = (Item) target;
if (!wcfg.getBlacklist().check(
new ItemAcquireBlacklistEvent(localPlayer,
toVector(target.getLocation()), createTarget(item.getItemStack())), false, true)) {
event.setCancelled(true);
return;
}
}
Material material = Materials.getRelatedMaterial(target.getType());
if (material != null) {
// Not really a block but we only have one on-break blacklist event
if (!wcfg.getBlacklist().check(new BlockBreakBlacklistEvent(localPlayer, toVector(event.getTarget()), createTarget(material)), false, false)) {
event.setCancelled(true);
}
}
}
@EventHandler(ignoreCancelled = true)
public void onUseItem(UseItemEvent event) {
Player player = event.getCause().getFirstPlayer();
if (player == null) {
return;
}
LocalPlayer localPlayer = getPlugin().wrapPlayer(player);
ItemStack target = event.getItemStack();
WorldConfiguration wcfg = getWorldConfig(player);
// Blacklist guard
if (wcfg.getBlacklist() == null) {
return;
}
if (!wcfg.getBlacklist().check(new ItemUseBlacklistEvent(localPlayer, toVector(player.getLocation()), createTarget(target)), false, false)) {
event.setCancelled(true);
}
}
@EventHandler(ignoreCancelled = true)
public void onPlayerDropItem(PlayerDropItemEvent event) {
ConfigurationManager cfg = getPlugin().getGlobalStateManager();
WorldConfiguration wcfg = cfg.get(event.getPlayer().getWorld());
if (wcfg.getBlacklist() != null) {
Item ci = event.getItemDrop();
if (!wcfg.getBlacklist().check(
new ItemDropBlacklistEvent(getPlugin().wrapPlayer(event.getPlayer()),
toVector(ci.getLocation()), createTarget(ci.getItemStack())), false, false)) {
event.setCancelled(true);
}
}
}
@EventHandler(ignoreCancelled = true)
public void onBlockDispense(BlockDispenseEvent event) {
ConfigurationManager cfg = getPlugin().getGlobalStateManager();
WorldConfiguration wcfg = cfg.get(event.getBlock().getWorld());
if (wcfg.getBlacklist() != null) {
if (!wcfg.getBlacklist().check(new BlockDispenseBlacklistEvent(null, toVector(event.getBlock()), createTarget(event.getItem())), false, false)) {
event.setCancelled(true);
}
}
}
}

View File

@ -17,14 +17,13 @@
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package com.sk89q.worldguard.internal.listener;
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.internal.cause.Causes;
import com.sk89q.worldguard.internal.event.ItemInteractEvent;
import com.sk89q.worldguard.bukkit.event.inventory.UseItemEvent;
import org.bukkit.ChatColor;
import org.bukkit.Material;
import org.bukkit.entity.Player;
@ -49,9 +48,9 @@ public BlockedPotionsListener(WorldGuardPlugin plugin) {
}
@EventHandler
public void onItemInteract(ItemInteractEvent event) {
public void onItemInteract(UseItemEvent event) {
// We only care about player caused events
if (!Causes.mayInvolvePlayer(event.getCauses())) {
if (event.getCause().getFirstPlayer() == null) {
return;
}
@ -84,7 +83,7 @@ public void onItemInteract(ItemInteractEvent event) {
}
if (blockedEffect != null) {
Player player = Causes.getInvolvedPlayer(event.getCauses());
Player player = event.getCause().getFirstPlayer();
if (player != null) {
if (getPlugin().hasPermission(player, "worldguard.override.potions")) {

View File

@ -0,0 +1,202 @@
/*
* 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.google.common.base.Predicate;
import com.sk89q.worldedit.blocks.BlockID;
import com.sk89q.worldguard.bukkit.WorldConfiguration;
import com.sk89q.worldguard.bukkit.WorldGuardPlugin;
import com.sk89q.worldguard.bukkit.event.block.BreakBlockEvent;
import com.sk89q.worldguard.bukkit.event.block.PlaceBlockEvent;
import com.sk89q.worldguard.bukkit.event.block.UseBlockEvent;
import org.bukkit.ChatColor;
import org.bukkit.Location;
import org.bukkit.entity.Player;
import org.bukkit.event.EventHandler;
import org.bukkit.event.block.SignChangeEvent;
/**
* Handle events that need to be processed by the chest protection.
*/
public class ChestProtectionListener extends AbstractListener {
/**
* Construct the listener.
*
* @param plugin an instance of WorldGuardPlugin
*/
public ChestProtectionListener(WorldGuardPlugin plugin) {
super(plugin);
}
@EventHandler(ignoreCancelled = true)
public void onPlaceBlock(final PlaceBlockEvent event) {
final Player player = event.getCause().getFirstPlayer();
if (player != null) {
final WorldConfiguration wcfg = getWorldConfig(player);
// Early guard
if (!wcfg.signChestProtection) {
return;
}
event.filter(new Predicate<Location>() {
@Override
public boolean apply(Location target) {
if (wcfg.getChestProtection().isChest(event.getEffectiveMaterial().getId()) && wcfg.isChestProtected(target.getBlock(), player)) {
player.sendMessage(ChatColor.DARK_RED + "This spot is for a chest that you don't have permission for.");
return false;
}
return true;
}
}, true);
}
}
@EventHandler(ignoreCancelled = true)
public void onBreakBlock(final BreakBlockEvent event) {
final Player player = event.getCause().getFirstPlayer();
final WorldConfiguration wcfg = getWorldConfig(event.getWorld());
// Early guard
if (!wcfg.signChestProtection) {
return;
}
if (player != null) {
event.filter(new Predicate<Location>() {
@Override
public boolean apply(Location target) {
if (wcfg.isChestProtected(target.getBlock(), player)) {
player.sendMessage(ChatColor.DARK_RED + "This chest is protected.");
return false;
}
return true;
}
}, true);
} else {
event.filter(new Predicate<Location>() {
@Override
public boolean apply(Location target) {
return !wcfg.isChestProtected(target.getBlock());
}
});
}
}
@EventHandler(ignoreCancelled = true)
public void onUseBlock(final UseBlockEvent event) {
final Player player = event.getCause().getFirstPlayer();
final WorldConfiguration wcfg = getWorldConfig(event.getWorld());
// Early guard
if (!wcfg.signChestProtection) {
return;
}
if (player != null) {
event.filter(new Predicate<Location>() {
@Override
public boolean apply(Location target) {
if (wcfg.isChestProtected(target.getBlock(), player)) {
player.sendMessage(ChatColor.DARK_RED + "This chest is protected.");
return false;
}
return true;
}
}, true);
} else {
event.filter(new Predicate<Location>() {
@Override
public boolean apply(Location target) {
return !wcfg.isChestProtected(target.getBlock());
}
});
}
}
@EventHandler(ignoreCancelled = true)
public void onSignChange(SignChangeEvent event) {
Player player = event.getPlayer();
WorldConfiguration wcfg = getWorldConfig(player);
if (wcfg.signChestProtection) {
if (event.getLine(0).equalsIgnoreCase("[Lock]")) {
if (wcfg.isChestProtectedPlacement(event.getBlock(), player)) {
player.sendMessage(ChatColor.DARK_RED + "You do not own the adjacent chest.");
event.getBlock().breakNaturally();
event.setCancelled(true);
return;
}
if (event.getBlock().getTypeId() != BlockID.SIGN_POST) {
player.sendMessage(ChatColor.RED
+ "The [Lock] sign must be a sign post, not a wall sign.");
event.getBlock().breakNaturally();
event.setCancelled(true);
return;
}
if (!event.getLine(1).equalsIgnoreCase(player.getName())) {
player.sendMessage(ChatColor.RED
+ "The first owner line must be your name.");
event.getBlock().breakNaturally();
event.setCancelled(true);
return;
}
int below = event.getBlock().getRelative(0, -1, 0).getTypeId();
if (below == BlockID.TNT || below == BlockID.SAND
|| below == BlockID.GRAVEL || below == BlockID.SIGN_POST) {
player.sendMessage(ChatColor.RED
+ "That is not a safe block that you're putting this sign on.");
event.getBlock().breakNaturally();
event.setCancelled(true);
return;
}
event.setLine(0, "[Lock]");
player.sendMessage(ChatColor.YELLOW
+ "A chest or double chest above is now protected.");
}
} else if (!wcfg.disableSignChestProtectionCheck) {
if (event.getLine(0).equalsIgnoreCase("[Lock]")) {
player.sendMessage(ChatColor.RED
+ "WorldGuard's sign chest protection is disabled.");
event.getBlock().breakNaturally();
event.setCancelled(true);
}
}
}
}

View File

@ -0,0 +1,205 @@
/*
* WorldGuard, a suite of tools for Minecraft
* Copyright (C) sk89q <http://www.sk89q.com>
* Copyright (C) WorldGuard team and contributors
*
* This program is free software: you can redistribute it and/or modify it
* under the terms of the GNU Lesser General Public License as published by the
* Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License
* for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package com.sk89q.worldguard.bukkit.listener;
import com.sk89q.worldguard.bukkit.WorldGuardPlugin;
import com.sk89q.worldguard.bukkit.event.block.BreakBlockEvent;
import com.sk89q.worldguard.bukkit.event.block.PlaceBlockEvent;
import com.sk89q.worldguard.bukkit.event.block.UseBlockEvent;
import com.sk89q.worldguard.bukkit.event.entity.DestroyEntityEvent;
import com.sk89q.worldguard.bukkit.event.entity.SpawnEntityEvent;
import com.sk89q.worldguard.bukkit.event.entity.UseEntityEvent;
import com.sk89q.worldguard.bukkit.event.inventory.UseItemEvent;
import org.bukkit.Location;
import org.bukkit.block.Block;
import org.bukkit.event.Event;
import org.bukkit.event.EventHandler;
import org.bukkit.event.EventPriority;
import javax.annotation.Nullable;
import java.util.List;
import java.util.logging.Logger;
import static com.google.common.base.Preconditions.checkNotNull;
public class DebuggingListener extends AbstractListener {
private final Logger logger;
/**
* Construct the listener.
*
* @param plugin an instance of WorldGuardPlugin
* @param logger the logger
*/
public DebuggingListener(WorldGuardPlugin plugin, Logger logger) {
super(plugin);
checkNotNull(logger);
this.logger = logger;
}
@EventHandler(priority = EventPriority.MONITOR)
public void onPlaceBlock(PlaceBlockEvent event) {
StringBuilder builder = new StringBuilder();
builder.append("PLACE");
builder.append(" ");
builder.append("").append(event.getEffectiveMaterial());
builder.append(" ");
builder.append("@").append(toBlockString(event.getBlocks()));
builder.append(" ");
builder.append("[").append(event.getCause()).append("]");
builder.append(" ");
builder.append(":").append(getEventName(event.getOriginalEvent()));
if (event.isCancelled()) {
builder.append(" [CANCELLED]");
}
logger.info(builder.toString());
}
@EventHandler(priority = EventPriority.MONITOR)
public void onBreakBlock(BreakBlockEvent event) {
StringBuilder builder = new StringBuilder();
builder.append("DIG");
builder.append(" ");
builder.append("").append(event.getEffectiveMaterial());
builder.append(" ");
builder.append("[").append(event.getCause()).append("]");
builder.append(" ");
builder.append("@").append(toBlockString(event.getBlocks()));
builder.append(" ");
builder.append(":").append(getEventName(event.getOriginalEvent()));
if (event.isCancelled()) {
builder.append(" [CANCELLED]");
}
logger.info(builder.toString());
}
@EventHandler(priority = EventPriority.MONITOR)
public void onUseBlock(UseBlockEvent event) {
StringBuilder builder = new StringBuilder();
builder.append("INTERACT");
builder.append(" ");
builder.append("").append(event.getEffectiveMaterial());
builder.append(" ");
builder.append("[").append(event.getCause()).append("]");
builder.append(" ");
builder.append("@").append(toBlockString(event.getBlocks()));
builder.append(" ");
builder.append(":").append(getEventName(event.getOriginalEvent()));
if (event.isCancelled()) {
builder.append(" [CANCELLED]");
}
logger.info(builder.toString());
}
@EventHandler(priority = EventPriority.MONITOR)
public void onSpawnEntity(SpawnEntityEvent event) {
StringBuilder builder = new StringBuilder();
builder.append("SPAWN");
builder.append(" ");
builder.append("").append(event.getEffectiveType());
builder.append(" ");
builder.append("[").append(event.getCause()).append("]");
builder.append(" ");
builder.append("@").append(toBlockString(event.getTarget()));
builder.append(" ");
builder.append(":").append(getEventName(event.getOriginalEvent()));
if (event.isCancelled()) {
builder.append(" [CANCELLED]");
}
logger.info(builder.toString());
}
@EventHandler(priority = EventPriority.MONITOR)
public void onDestroyEntity(DestroyEntityEvent event) {
StringBuilder builder = new StringBuilder();
builder.append("DESTROY");
builder.append(" ");
builder.append("").append(event.getEntity().getType());
builder.append(" ");
builder.append("[").append(event.getCause()).append("]");
builder.append(" ");
builder.append("@").append(toBlockString(event.getTarget()));
builder.append(" ");
builder.append(":").append(getEventName(event.getOriginalEvent()));
if (event.isCancelled()) {
builder.append(" [CANCELLED]");
}
logger.info(builder.toString());
}
@EventHandler(priority = EventPriority.MONITOR)
public void onUseEntity(UseEntityEvent event) {
StringBuilder builder = new StringBuilder();
builder.append("INTERACT");
builder.append(" ");
builder.append("").append(event.getEntity().getType());
builder.append(" ");
builder.append("[").append(event.getCause()).append("]");
builder.append(" ");
builder.append("@").append(toBlockString(event.getTarget()));
builder.append(" ");
builder.append(":").append(getEventName(event.getOriginalEvent()));
if (event.isCancelled()) {
builder.append(" [CANCELLED]");
}
logger.info(builder.toString());
}
@EventHandler(priority = EventPriority.MONITOR)
public void onUseItem(UseItemEvent event) {
StringBuilder builder = new StringBuilder();
builder.append("USE");
builder.append(" ");
builder.append("").append(event.getItemStack().getType());
builder.append(" ");
builder.append("[").append(event.getCause()).append("]");
builder.append(" ");
builder.append("@").append(event.getWorld().getName());
builder.append(" ");
builder.append(":").append(getEventName(event.getOriginalEvent()));
if (event.isCancelled()) {
builder.append(" [CANCELLED]");
}
logger.info(builder.toString());
}
private static String toBlockString(Location location) {
return location.getBlockX() + "," + location.getBlockY() + "," + location.getBlockZ();
}
private static String toBlockString(List<Block> blocks) {
StringBuilder builder = new StringBuilder();
boolean first = true;
for (Block block : blocks) {
if (!first) {
builder.append("|");
}
builder.append(block.getX()).append(",").append(block.getY()).append(",").append(block.getZ());
first = false;
}
return builder.toString();
}
private String getEventName(@Nullable Event event) {
return event != null ? event.getEventName() : "?";
}
}

View File

@ -0,0 +1,665 @@
/*
* 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.google.common.collect.Lists;
import com.sk89q.worldguard.bukkit.WorldConfiguration;
import com.sk89q.worldguard.bukkit.WorldGuardPlugin;
import com.sk89q.worldguard.bukkit.cause.Cause;
import com.sk89q.worldguard.bukkit.event.block.BreakBlockEvent;
import com.sk89q.worldguard.bukkit.event.block.PlaceBlockEvent;
import com.sk89q.worldguard.bukkit.event.block.UseBlockEvent;
import com.sk89q.worldguard.bukkit.event.entity.DamageEntityEvent;
import com.sk89q.worldguard.bukkit.event.entity.DestroyEntityEvent;
import com.sk89q.worldguard.bukkit.event.entity.SpawnEntityEvent;
import com.sk89q.worldguard.bukkit.event.entity.UseEntityEvent;
import com.sk89q.worldguard.bukkit.event.inventory.UseItemEvent;
import com.sk89q.worldguard.bukkit.listener.debounce.BlockEntityEventDebounce;
import com.sk89q.worldguard.bukkit.listener.debounce.EntityEntityEventDebounce;
import com.sk89q.worldguard.bukkit.util.BlockStateAsBlockFunction;
import com.sk89q.worldguard.bukkit.util.Blocks;
import com.sk89q.worldguard.bukkit.util.Events;
import com.sk89q.worldguard.bukkit.util.Materials;
import org.bukkit.DyeColor;
import org.bukkit.Material;
import org.bukkit.World;
import org.bukkit.block.Block;
import org.bukkit.block.BlockFace;
import org.bukkit.block.BlockState;
import org.bukkit.entity.Entity;
import org.bukkit.entity.EntityType;
import org.bukkit.entity.FallingBlock;
import org.bukkit.entity.Item;
import org.bukkit.entity.LivingEntity;
import org.bukkit.entity.Player;
import org.bukkit.entity.ThrownPotion;
import org.bukkit.event.Cancellable;
import org.bukkit.event.Event;
import org.bukkit.event.Event.Result;
import org.bukkit.event.EventHandler;
import org.bukkit.event.block.Action;
import org.bukkit.event.block.BlockBreakEvent;
import org.bukkit.event.block.BlockBurnEvent;
import org.bukkit.event.block.BlockDamageEvent;
import org.bukkit.event.block.BlockDispenseEvent;
import org.bukkit.event.block.BlockExpEvent;
import org.bukkit.event.block.BlockFromToEvent;
import org.bukkit.event.block.BlockIgniteEvent;
import org.bukkit.event.block.BlockIgniteEvent.IgniteCause;
import org.bukkit.event.block.BlockPistonExtendEvent;
import org.bukkit.event.block.BlockPistonRetractEvent;
import org.bukkit.event.block.BlockPlaceEvent;
import org.bukkit.event.block.SignChangeEvent;
import org.bukkit.event.entity.CreatureSpawnEvent;
import org.bukkit.event.entity.EntityChangeBlockEvent;
import org.bukkit.event.entity.EntityCombustByBlockEvent;
import org.bukkit.event.entity.EntityCombustByEntityEvent;
import org.bukkit.event.entity.EntityCombustEvent;
import org.bukkit.event.entity.EntityDamageByBlockEvent;
import org.bukkit.event.entity.EntityDamageByEntityEvent;
import org.bukkit.event.entity.EntityDamageEvent;
import org.bukkit.event.entity.EntityDeathEvent;
import org.bukkit.event.entity.EntityExplodeEvent;
import org.bukkit.event.entity.EntityTameEvent;
import org.bukkit.event.entity.EntityUnleashEvent;
import org.bukkit.event.entity.ExpBottleEvent;
import org.bukkit.event.entity.PotionSplashEvent;
import org.bukkit.event.hanging.HangingBreakByEntityEvent;
import org.bukkit.event.hanging.HangingBreakEvent;
import org.bukkit.event.hanging.HangingPlaceEvent;
import org.bukkit.event.player.PlayerBedEnterEvent;
import org.bukkit.event.player.PlayerBucketEmptyEvent;
import org.bukkit.event.player.PlayerBucketFillEvent;
import org.bukkit.event.player.PlayerDropItemEvent;
import org.bukkit.event.player.PlayerFishEvent;
import org.bukkit.event.player.PlayerInteractEntityEvent;
import org.bukkit.event.player.PlayerInteractEvent;
import org.bukkit.event.player.PlayerPickupItemEvent;
import org.bukkit.event.player.PlayerShearEntityEvent;
import org.bukkit.event.player.PlayerUnleashEntityEvent;
import org.bukkit.event.vehicle.VehicleDamageEvent;
import org.bukkit.event.vehicle.VehicleDestroyEvent;
import org.bukkit.event.world.StructureGrowEvent;
import org.bukkit.inventory.ItemStack;
import org.bukkit.material.Dispenser;
import org.bukkit.material.MaterialData;
import org.bukkit.util.Vector;
import javax.annotation.Nullable;
import java.util.ArrayList;
import java.util.List;
import static com.sk89q.worldguard.bukkit.cause.Cause.create;
import static com.sk89q.worldguard.bukkit.util.Materials.isBlockModifiedOnClick;
import static com.sk89q.worldguard.bukkit.util.Materials.isItemAppliedToBlock;
public class EventAbstractionListener extends AbstractListener {
private final BlockEntityEventDebounce interactDebounce = new BlockEntityEventDebounce(10000);
private final EntityEntityEventDebounce pickupDebounce = new EntityEntityEventDebounce(10000);
/**
* Construct the listener.
*
* @param plugin an instance of WorldGuardPlugin
*/
public EventAbstractionListener(WorldGuardPlugin plugin) {
super(plugin);
}
public void registerEvents() {
getPlugin().getServer().getPluginManager().registerEvents(this, getPlugin());
}
//-------------------------------------------------------------------------
// Block break / place
//-------------------------------------------------------------------------
@EventHandler
public void onBlockBreak(BlockBreakEvent event) {
Events.fireToCancel(event, new BreakBlockEvent(event, create(event.getPlayer()), event.getBlock()));
}
@EventHandler
public void onBlockPlace(BlockPlaceEvent event) {
BlockState previousState = event.getBlockReplacedState();
// Some blocks, like tall grass and fire, get replaced
if (previousState.getType() != Material.AIR) {
Events.fireToCancel(event, new BreakBlockEvent(event, create(event.getPlayer()), previousState.getLocation(), previousState.getType()));
}
Events.fireToCancel(event, new PlaceBlockEvent(event, create(event.getPlayer()), event.getBlock()));
}
@EventHandler
public void onBlockBurn(BlockBurnEvent event) {
Events.fireToCancel(event, new UseBlockEvent(event, Cause.unknown(), event.getBlock()));
}
@EventHandler
public void onStructureGrowEvent(StructureGrowEvent event) {
List<Block> blockList = Lists.transform(event.getBlocks(), new BlockStateAsBlockFunction());
Events.fireBulkEventToCancel(event, new PlaceBlockEvent(event, create(event.getPlayer()), event.getLocation().getWorld(), blockList, Material.AIR));
}
// TODO: Handle EntityCreatePortalEvent?
@EventHandler
public void onEntityChangeBlock(EntityChangeBlockEvent event) {
Block block = event.getBlock();
Entity entity = event.getEntity();
Material to = event.getTo();
// Fire two events: one as BREAK and one as PLACE
if (event.getTo() != Material.AIR && event.getBlock().getType() != Material.AIR) {
Events.fireToCancel(event, new BreakBlockEvent(event, create(entity), block));
Events.fireToCancel(event, new PlaceBlockEvent(event, create(entity), block.getLocation(), to));
} else {
if (event.getTo() == Material.AIR) {
// Track the source so later we can create a proper chain of causes
if (entity instanceof FallingBlock) {
Cause.trackParentCause(entity, block);
// Switch around the event
Events.fireToCancel(event, new SpawnEntityEvent(event, create(block), entity));
} else {
Events.fireToCancel(event, new BreakBlockEvent(event, create(entity), event.getBlock()));
}
} else {
boolean wasCancelled = event.isCancelled();
Cause cause = create(entity);
Events.fireToCancel(event, new PlaceBlockEvent(event, cause, event.getBlock().getLocation(), to));
if (event.isCancelled() && !wasCancelled && entity instanceof FallingBlock) {
FallingBlock fallingBlock = (FallingBlock) entity;
ItemStack itemStack = new ItemStack(fallingBlock.getMaterial(), 1, fallingBlock.getBlockData());
Item item = block.getWorld().dropItem(fallingBlock.getLocation(), itemStack);
item.setVelocity(new Vector());
if (Events.fireAndTestCancel(new SpawnEntityEvent(event, create(block, entity), item))) {
item.remove();
}
}
}
}
}
@EventHandler
public void onEntityExplode(EntityExplodeEvent event) {
Entity entity = event.getEntity();
Events.fireBulkEventToCancel(event, new BreakBlockEvent(event, create(entity), event.getLocation().getWorld(), event.blockList(), Material.AIR));
}
@EventHandler
public void onBlockPistonRetract(BlockPistonRetractEvent event) {
if (event.isSticky()) {
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())));
}
}
@EventHandler
public void onBlockPistonExtend(BlockPistonExtendEvent event) {
// A hack for now
List<Block> blocks = new ArrayList<Block>(event.getBlocks());
Block lastBlock = event.getBlock().getRelative(event.getDirection(), event.getLength() + 1);
blocks.add(lastBlock);
int originalLength = blocks.size();
Events.fireBulkEventToCancel(event, new PlaceBlockEvent(event, create(event.getBlock()), event.getBlock().getWorld(), blocks, Material.STONE));
if (blocks.size() != originalLength) {
event.setCancelled(true);
}
}
//-------------------------------------------------------------------------
// Block external interaction
//-------------------------------------------------------------------------
@EventHandler
public void onBlockDamage(BlockDamageEvent event) {
Block target = event.getBlock();
// Previously, and perhaps still, the only way to catch cake eating
// events was through here
if (target.getType() == Material.CAKE_BLOCK) {
Events.fireToCancel(event, new UseBlockEvent(event, create(event.getPlayer()), target));
}
}
@EventHandler
public void onPlayerInteract(PlayerInteractEvent event) {
Player player = event.getPlayer();
@Nullable ItemStack item = player.getItemInHand();
Block clicked = event.getClickedBlock();
Block placed;
Cause cause = create(player);
switch (event.getAction()) {
case PHYSICAL:
interactDebounce.debounce(clicked, event.getPlayer(), event, new UseBlockEvent(event, cause, clicked));
break;
case RIGHT_CLICK_BLOCK:
placed = clicked.getRelative(event.getBlockFace());
// Re-used for dispensers
handleBlockRightClick(event, create(event.getPlayer()), item, clicked, event.getBlockFace(), placed);
case LEFT_CLICK_BLOCK:
placed = clicked.getRelative(event.getBlockFace());
// As of MC ~1.6, sneaking blocks the use of blocks with right click
if (!player.isSneaking() || event.getAction() == Action.LEFT_CLICK_BLOCK) {
// Only fire events for blocks that are modified when right clicked
if (isBlockModifiedOnClick(clicked.getType()) || (item != null && isItemAppliedToBlock(item.getType(), clicked.getType()))) {
if (Events.fireAndTestCancel(new UseBlockEvent(event, cause, clicked))) {
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))) {
event.setUseInteractedBlock(Result.DENY);
break;
}
}
}
}
// Special handling of putting out fires
if (event.getAction() == Action.LEFT_CLICK_BLOCK && placed.getType() == Material.FIRE) {
if (Events.fireAndTestCancel(new BreakBlockEvent(event, create(event.getPlayer()), placed))) {
event.setUseInteractedBlock(Result.DENY);
break;
}
}
case LEFT_CLICK_AIR:
case RIGHT_CLICK_AIR:
if (item != null && !item.getType().isBlock() && Events.fireAndTestCancel(new UseItemEvent(event, cause, player.getWorld(), item))) {
event.setUseItemInHand(Result.DENY);
}
break;
}
}
@EventHandler
public void onEntityInteract(org.bukkit.event.entity.EntityInteractEvent event) {
interactDebounce.debounce(event.getBlock(), event.getEntity(), event, new UseBlockEvent(event, create(event.getEntity()), event.getBlock()));
}
@EventHandler
public void onBlockIgnite(BlockIgniteEvent event) {
Block block = event.getBlock();
Cause cause;
// Find the cause
if (event.getPlayer() != null) {
cause = create(event.getPlayer());
} else if (event.getIgnitingEntity() != null) {
cause = create(event.getIgnitingEntity());
} else if (event.getIgnitingBlock() != null) {
cause = create(event.getIgnitingBlock());
} else {
cause = Cause.unknown();
}
if (block.getType() != Material.AIR) {
Events.fireToCancel(event, new BreakBlockEvent(event, cause, event.getBlock()));
}
// This is also handled in the PlayerInteractEvent listener
if (event.getCause() == IgniteCause.FLINT_AND_STEEL || event.getCause() == IgniteCause.FIREBALL) {
// TODO: Test location of block
Events.fireToCancel(event, new PlaceBlockEvent(event, cause, event.getBlock().getLocation(), Material.FIRE));
}
}
@EventHandler
public void onSignChange(SignChangeEvent event) {
Events.fireToCancel(event, new UseBlockEvent(event, create(event.getPlayer()), event.getBlock()));
}
@EventHandler
public void onBedEnter(PlayerBedEnterEvent event) {
Events.fireToCancel(event, new UseBlockEvent(event, create(event.getPlayer()), event.getBed()));
}
@EventHandler
public void onPlayerBucketEmpty(PlayerBucketEmptyEvent event) {
Player player = event.getPlayer();
Block blockAffected = event.getBlockClicked().getRelative(event.getBlockFace());
// 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));
}
}
@EventHandler
public void onPlayerBucketFill(PlayerBucketFillEvent event) {
Player player = event.getPlayer();
Block blockAffected = event.getBlockClicked().getRelative(event.getBlockFace());
// 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));
}
}
// TODO: Handle EntityPortalEnterEvent
//-------------------------------------------------------------------------
// Block self-interaction
//-------------------------------------------------------------------------
@EventHandler
public void onBlockFromTo(BlockFromToEvent event) {
WorldConfiguration config = getWorldConfig(event.getBlock().getWorld());
// This only applies to regions but nothing else cares about high
// frequency events at the moment
if (!config.useRegions || (!config.highFreqFlags && !config.checkLiquidFlow)) {
return;
}
Block from = event.getBlock();
Block to = event.getToBlock();
Material fromType = from.getType();
Material toType = to.getType();
// Liquids pass this event when flowing to solid blocks
if (toType.isSolid() && Materials.isLiquid(fromType)) {
return;
}
// This significantly reduces the number of events without having
// too much effect. Unfortunately it appears that even if this
// check didn't exist, you can raise the level of some liquid
// flow and the from/to data may not be correct.
if ((Materials.isWater(fromType) && Materials.isWater(toType)) || (Materials.isLava(fromType) && Materials.isLava(toType))) {
return;
}
Cause cause = create(from);
// Disable since it's probably not needed
/*if (from.getType() != Material.AIR) {
Events.fireToCancel(event, new BreakBlockEvent(event, cause, to));
}*/
Events.fireToCancel(event, new PlaceBlockEvent(event, cause, to.getLocation(), from.getType()));
}
//-------------------------------------------------------------------------
// Entity break / place
//-------------------------------------------------------------------------
@EventHandler
public void onCreatureSpawn(CreatureSpawnEvent event) {
Events.fireToCancel(event, new SpawnEntityEvent(event, Cause.unknown(), event.getEntity()));
}
@EventHandler
public void onHangingPlace(HangingPlaceEvent event) {
Events.fireToCancel(event, new SpawnEntityEvent(event, create(event.getPlayer()), event.getEntity()));
}
@EventHandler
public void onHangingBreak(HangingBreakEvent event) {
if (event instanceof HangingBreakByEntityEvent) {
Events.fireToCancel(event, new DestroyEntityEvent(event, create(((HangingBreakByEntityEvent) event).getRemover()), event.getEntity()));
} else {
Events.fireToCancel(event, new DestroyEntityEvent(event, Cause.unknown(), event.getEntity()));
}
}
@EventHandler
public void onVehicleDestroy(VehicleDestroyEvent event) {
Events.fireToCancel(event, new DestroyEntityEvent(event, create(event.getAttacker()), event.getVehicle()));
}
@EventHandler
public void onBlockExp(BlockExpEvent event) {
if (event.getExpToDrop() > 0) { // Event is raised even where no XP is being dropped
if (Events.fireAndTestCancel(new SpawnEntityEvent(event, create(event.getBlock()), event.getBlock().getLocation(), EntityType.EXPERIENCE_ORB))) {
event.setExpToDrop(0);
}
}
}
@EventHandler
public void onPlayerFish(PlayerFishEvent event) {
if (Events.fireAndTestCancel(new SpawnEntityEvent(event, create(event.getPlayer(), event.getHook()), event.getCaught().getLocation(), EntityType.EXPERIENCE_ORB))) {
event.setExpToDrop(0);
}
}
@EventHandler
public void onExpBottle(ExpBottleEvent event) {
if (Events.fireAndTestCancel(new SpawnEntityEvent(event, create(event.getEntity()), event.getEntity().getLocation(), EntityType.EXPERIENCE_ORB))) {
event.setExperience(0);
}
}
@EventHandler
public void onEntityDeath(EntityDeathEvent event) {
if (event.getDroppedExp() > 0) {
if (Events.fireAndTestCancel(new SpawnEntityEvent(event, create(event.getEntity()), event.getEntity().getLocation(), EntityType.EXPERIENCE_ORB))) {
event.setDroppedExp(0);
}
}
}
//-------------------------------------------------------------------------
// Entity external interaction
//-------------------------------------------------------------------------
@EventHandler
public void onPlayerInteractEntity(PlayerInteractEntityEvent event) {
Player player = event.getPlayer();
World world = player.getWorld();
ItemStack item = player.getItemInHand();
Entity entity = event.getRightClicked();
Events.fireToCancel(event, new UseItemEvent(event, create(player), world, item));
Events.fireToCancel(event, new UseEntityEvent(event, create(player), entity));
}
@EventHandler
public void onEntityDamage(EntityDamageEvent event) {
if (event instanceof EntityDamageByBlockEvent) {
Events.fireToCancel(event, new DamageEntityEvent(event, create(((EntityDamageByBlockEvent) event).getDamager()), event.getEntity()));
} else if (event instanceof EntityDamageByEntityEvent) {
EntityDamageByEntityEvent entityEvent = (EntityDamageByEntityEvent) event;
Entity damager = entityEvent.getDamager();
Events.fireToCancel(event, new DamageEntityEvent(event, create(damager), event.getEntity()));
// Item use event with the item in hand
// Older blacklist handler code used this, although it suffers from
// race problems
if (damager instanceof Player) {
ItemStack item = ((Player) damager).getItemInHand();
if (item != null) {
Events.fireToCancel(event, new UseItemEvent(event, create(damager), event.getEntity().getWorld(), item));
}
}
} else {
Events.fireToCancel(event, new DamageEntityEvent(event, Cause.unknown(), event.getEntity()));
}
}
@EventHandler
public void onEntityCombust(EntityCombustEvent event) {
if (event instanceof EntityCombustByBlockEvent) {
Events.fireToCancel(event, new DamageEntityEvent(event, create(((EntityCombustByBlockEvent) event).getCombuster()), event.getEntity()));
} else if (event instanceof EntityCombustByEntityEvent) {
Events.fireToCancel(event, new DamageEntityEvent(event, create(((EntityCombustByEntityEvent) event).getCombuster()), event.getEntity()));
} else {
Events.fireToCancel(event, new DamageEntityEvent(event, Cause.unknown(), event.getEntity()));
}
}
@EventHandler
public void onEntityUnleash(EntityUnleashEvent event) {
if (event instanceof PlayerUnleashEntityEvent) {
PlayerUnleashEntityEvent playerEvent = (PlayerUnleashEntityEvent) event;
Events.fireToCancel(playerEvent, new UseEntityEvent(playerEvent, create(playerEvent.getPlayer()), event.getEntity()));
} else {
// TODO: Raise anyway?
}
}
@EventHandler
public void onEntityTame(EntityTameEvent event) {
Events.fireToCancel(event, new UseEntityEvent(event, create(event.getOwner()), event.getEntity()));
}
@EventHandler
public void onPlayerShearEntity(PlayerShearEntityEvent event) {
Events.fireToCancel(event, new UseEntityEvent(event, create(event.getPlayer()), event.getEntity()));
}
@EventHandler
public void onPlayerPickupItem(PlayerPickupItemEvent event) {
Item item = event.getItem();
pickupDebounce.debounce(event.getPlayer(), item, event, new DestroyEntityEvent(event, create(event.getPlayer()), event.getItem()));
}
@EventHandler
public void onPlayerDropItem(PlayerDropItemEvent event) {
Events.fireToCancel(event, new SpawnEntityEvent(event, create(event.getPlayer()), event.getItemDrop()));
}
@EventHandler
public void onVehicleDamage(VehicleDamageEvent event) {
Events.fireToCancel(event, new DestroyEntityEvent(event, create(event.getAttacker()), event.getVehicle()));
}
@EventHandler
public void onVehicleEnter(VehicleDamageEvent event) {
Events.fireToCancel(event, new UseEntityEvent(event, create(event.getAttacker()), event.getVehicle()));
}
//-------------------------------------------------------------------------
// Composite events
//-------------------------------------------------------------------------
@EventHandler
public void onPotionSplash(PotionSplashEvent event) {
Entity entity = event.getEntity();
ThrownPotion potion = event.getPotion();
World world = entity.getWorld();
Cause cause = create(potion.getShooter());
// Fire item interaction event
Events.fireToCancel(event, new UseItemEvent(event, cause, world, potion.getItem()));
// Fire entity interaction event
if (!event.isCancelled()) {
int blocked = 0;
for (LivingEntity affected : event.getAffectedEntities()) {
if (Events.fireAndTestCancel(new UseEntityEvent(event, cause, affected))) {
event.setIntensity(affected, 0);
blocked++;
}
}
if (blocked == event.getAffectedEntities().size()) {
event.setCancelled(true);
}
}
}
@EventHandler
public void onBlockDispense(BlockDispenseEvent event) {
Cause cause = create(event.getBlock());
Block dispenserBlock = event.getBlock();
ItemStack item = event.getItem();
MaterialData materialData = dispenserBlock.getState().getData();
Events.fireToCancel(event, new UseItemEvent(event, cause, dispenserBlock.getWorld(), item));
// Simulate right click event as players have it
if (materialData instanceof Dispenser) {
Dispenser dispenser = (Dispenser) materialData;
Block placed = dispenserBlock.getRelative(dispenser.getFacing());
Block clicked = placed.getRelative(dispenser.getFacing());
handleBlockRightClick(event, cause, item, clicked, dispenser.getFacing().getOppositeFace(), placed);
}
}
/**
* Handle the right click of a block while an item is held.
*
* @param event the original event
* @param cause the list of cause
* @param item the item
* @param clicked the clicked block
* @param faceClicked the face of the clicked block
* @param placed the placed block
* @param <T> the event type
*/
private static <T extends Event & Cancellable> void handleBlockRightClick(T event, Cause cause, @Nullable ItemStack item, Block clicked, BlockFace faceClicked, Block placed) {
if (item != null && item.getType() == Material.TNT) {
// Workaround for a bug that allowed TNT to trigger instantly if placed
// next to redstone, without plugins getting the clicked place event
// (not sure if this actually still happens)
Events.fireToCancel(event, new UseBlockEvent(event, cause, clicked.getLocation(), Material.TNT));
}
// Handle created Minecarts
if (item != null && Materials.isMinecart(item.getType())) {
// TODO: Give a more specific Minecart type
Events.fireToCancel(event, new SpawnEntityEvent(event, cause, placed.getLocation().add(0.5, 0, 0.5), EntityType.MINECART));
}
// Handle cocoa beans
if (item != null && item.getType() == Material.INK_SACK && Materials.isDyeColor(item.getData(), DyeColor.BROWN)) {
// CraftBukkit doesn't or didn't throw a clicked place for this
if (!(faceClicked == BlockFace.DOWN || faceClicked == BlockFace.UP)) {
Events.fireToCancel(event, new PlaceBlockEvent(event, cause, placed.getLocation(), Material.COCOA));
}
}
// Workaround for http://leaky.bukkit.org/issues/1034
if (item != null && item.getType() == Material.TNT) {
Events.fireToCancel(event, new PlaceBlockEvent(event, cause, placed.getLocation(), Material.TNT));
}
}
// TODO: Inventory events?
}

View File

@ -1,252 +1,250 @@
/*
* WorldGuard, a suite of tools for Minecraft
* Copyright (C) sk89q <http://www.sk89q.com>
* Copyright (C) WorldGuard team and contributors
*
* This program is free software: you can redistribute it and/or modify it
* under the terms of the GNU Lesser General Public License as published by the
* Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License
* for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package com.sk89q.worldguard.bukkit;
import com.sk89q.worldedit.Vector;
import com.sk89q.worldguard.protection.ApplicableRegionSet;
import com.sk89q.worldguard.protection.flags.DefaultFlag;
import com.sk89q.worldguard.protection.managers.RegionManager;
import org.bukkit.GameMode;
import org.bukkit.World;
import org.bukkit.entity.Player;
import java.util.HashMap;
import java.util.Map;
import static com.sk89q.worldguard.bukkit.BukkitUtil.toVector;
/**
* This processes per-player state information and is also meant to be used
* as a scheduled task.
*
* @author sk89q
*/
public class FlagStateManager implements Runnable {
public static final int RUN_DELAY = 20;
private WorldGuardPlugin plugin;
private Map<String, PlayerFlagState> states;
/**
* Construct the object.
*
* @param plugin The plugin instance
*/
public FlagStateManager(WorldGuardPlugin plugin) {
this.plugin = plugin;
states = new HashMap<String, PlayerFlagState>();
}
/**
* Run the task.
*/
@Override
public void run() {
Player[] players = plugin.getServer().getOnlinePlayers();
ConfigurationManager config = plugin.getGlobalStateManager();
for (Player player : players) {
WorldConfiguration worldConfig = config.get(player.getWorld());
if (!worldConfig.useRegions) {
continue;
}
PlayerFlagState state;
synchronized (this) {
state = states.get(player.getName());
if (state == null) {
state = new PlayerFlagState();
states.put(player.getName(), state);
}
}
Vector playerLocation = toVector(player.getLocation());
RegionManager regionManager = plugin.getGlobalRegionManager().get(player.getWorld());
ApplicableRegionSet applicable = regionManager.getApplicableRegions(playerLocation);
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;
}
}
/*
* WorldGuard, a suite of tools for Minecraft
* Copyright (C) sk89q <http://www.sk89q.com>
* Copyright (C) WorldGuard team and contributors
*
* This program is free software: you can redistribute it and/or modify it
* under the terms of the GNU Lesser General Public License as published by the
* Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License
* for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package com.sk89q.worldguard.bukkit.listener;
import com.sk89q.worldguard.bukkit.ConfigurationManager;
import com.sk89q.worldguard.bukkit.WorldConfiguration;
import com.sk89q.worldguard.bukkit.WorldGuardPlugin;
import com.sk89q.worldguard.bukkit.util.RegionQueryUtil;
import com.sk89q.worldguard.protection.ApplicableRegionSet;
import com.sk89q.worldguard.protection.flags.DefaultFlag;
import org.bukkit.GameMode;
import org.bukkit.World;
import org.bukkit.entity.Player;
import java.util.HashMap;
import java.util.Map;
/**
* This processes per-player state information and is also meant to be used
* as a scheduled task.
*
* @author sk89q
*/
public class FlagStateManager implements Runnable {
public static final int RUN_DELAY = 20;
private WorldGuardPlugin plugin;
private Map<String, PlayerFlagState> states;
/**
* Construct the object.
*
* @param plugin The plugin instance
*/
public FlagStateManager(WorldGuardPlugin plugin) {
this.plugin = plugin;
states = new HashMap<String, PlayerFlagState>();
}
/**
* Run the task.
*/
@Override
public void run() {
Player[] players = plugin.getServer().getOnlinePlayers();
ConfigurationManager config = plugin.getGlobalStateManager();
for (Player player : players) {
WorldConfiguration worldConfig = config.get(player.getWorld());
if (!worldConfig.useRegions) {
continue;
}
PlayerFlagState state;
synchronized (this) {
state = states.get(player.getName());
if (state == null) {
state = new PlayerFlagState();
states.put(player.getName(), state);
}
}
ApplicableRegionSet applicable = plugin.getRegionContainer().createQuery().getApplicableRegions(player.getLocation());
if (!RegionQueryUtil.isInvincible(plugin, player, applicable)
&& !plugin.getGlobalStateManager().hasGodMode(player)
&& !(player.getGameMode() == GameMode.CREATIVE)) {
processHeal(applicable, player, state);
processFeed(applicable, player, state);
}
}
}
/**
* Process healing for a player.
*
* @param applicable The set of applicable regions
* @param player The player to process healing flags on
* @param state The player's state
*/
private void processHeal(ApplicableRegionSet applicable, Player player,
PlayerFlagState state) {
if (player.getHealth() <= 0) {
return;
}
long now = System.currentTimeMillis();
Integer healAmount = applicable.getFlag(DefaultFlag.HEAL_AMOUNT);
Integer healDelay = applicable.getFlag(DefaultFlag.HEAL_DELAY);
Double minHealth = applicable.getFlag(DefaultFlag.MIN_HEAL);
Double maxHealth = applicable.getFlag(DefaultFlag.MAX_HEAL);
if (healAmount == null || healDelay == null || healAmount == 0 || healDelay < 0) {
return;
}
if (minHealth == null) {
minHealth = 0.0;
}
if (maxHealth == null) {
maxHealth = player.getMaxHealth();
}
// Apply a cap to prevent possible exceptions
minHealth = Math.min(player.getMaxHealth(), minHealth);
maxHealth = Math.min(player.getMaxHealth(), maxHealth);
if (player.getHealth() >= maxHealth && healAmount > 0) {
return;
}
if (healDelay <= 0) {
player.setHealth(healAmount > 0 ? maxHealth : minHealth); // this will insta-kill if the flag is unset
state.lastHeal = now;
} else if (now - state.lastHeal > healDelay * 1000) {
// clamp health between minimum and maximum
player.setHealth(Math.min(maxHealth, Math.max(minHealth, player.getHealth() + healAmount)));
state.lastHeal = now;
}
}
/**
* Process restoring hunger for a player.
*
* @param applicable The set of applicable regions
* @param player The player to process hunger flags on
* @param state The player's state
*/
private void processFeed(ApplicableRegionSet applicable, Player player,
PlayerFlagState state) {
long now = System.currentTimeMillis();
Integer feedAmount = applicable.getFlag(DefaultFlag.FEED_AMOUNT);
Integer feedDelay = applicable.getFlag(DefaultFlag.FEED_DELAY);
Integer minHunger = applicable.getFlag(DefaultFlag.MIN_FOOD);
Integer maxHunger = applicable.getFlag(DefaultFlag.MAX_FOOD);
if (feedAmount == null || feedDelay == null || feedAmount == 0 || feedDelay < 0) {
return;
}
if (minHunger == null) {
minHunger = 0;
}
if (maxHunger == null) {
maxHunger = 20;
}
// Apply a cap to prevent possible exceptions
minHunger = Math.min(20, minHunger);
maxHunger = Math.min(20, maxHunger);
if (player.getFoodLevel() >= maxHunger && feedAmount > 0) {
return;
}
if (feedDelay <= 0) {
player.setFoodLevel(feedAmount > 0 ? maxHunger : minHunger);
player.setSaturation(player.getFoodLevel());
state.lastFeed = now;
} else if (now - state.lastFeed > feedDelay * 1000) {
// clamp health between minimum and maximum
player.setFoodLevel(Math.min(maxHunger, Math.max(minHunger, player.getFoodLevel() + feedAmount)));
player.setSaturation(player.getFoodLevel());
state.lastFeed = now;
}
}
/**
* Forget a player.
*
* @param player The player to forget
*/
public synchronized void forget(Player player) {
states.remove(player.getName());
}
/**
* Forget all managed players. Use with caution.
*/
public synchronized void forgetAll() {
states.clear();
}
/**
* Get a player's flag state. A new state will be created if there is no existing
* state for the player.
*
* @param player The player to get a state for
* @return The {@code player}'s state
*/
public synchronized PlayerFlagState getState(Player player) {
PlayerFlagState state = states.get(player.getName());
if (state == null) {
state = new PlayerFlagState();
states.put(player.getName(), state);
}
return state;
}
/**
* Keeps state per player.
*/
public static class PlayerFlagState {
public long lastHeal;
public long lastFeed;
public String lastGreeting;
public String lastFarewell;
public Boolean lastExitAllowed = null;
public Boolean notifiedForLeave = false;
public Boolean notifiedForEnter = false;
public GameMode lastGameMode;
public World lastWorld;
public int lastBlockX;
public int lastBlockY;
public int lastBlockZ;
/* Used to cache invincibility status */
public World lastInvincibleWorld;
public int lastInvincibleX;
public int lastInvincibleY;
public int lastInvincibleZ;
public boolean wasInvincible;
}
}

View File

@ -0,0 +1,143 @@
/*
* 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.google.common.base.Predicate;
import com.sk89q.worldguard.bukkit.RegionQuery;
import com.sk89q.worldguard.bukkit.WorldConfiguration;
import com.sk89q.worldguard.bukkit.WorldGuardPlugin;
import com.sk89q.worldguard.bukkit.event.block.BreakBlockEvent;
import com.sk89q.worldguard.bukkit.event.block.PlaceBlockEvent;
import com.sk89q.worldguard.bukkit.event.entity.SpawnEntityEvent;
import com.sk89q.worldguard.bukkit.util.Materials;
import com.sk89q.worldguard.protection.flags.DefaultFlag;
import com.sk89q.worldguard.protection.flags.StateFlag;
import org.bukkit.Location;
import org.bukkit.block.Block;
import org.bukkit.entity.Creeper;
import org.bukkit.entity.EnderDragon;
import org.bukkit.entity.Entity;
import org.bukkit.entity.EntityType;
import org.bukkit.event.EventHandler;
import org.bukkit.event.EventPriority;
import javax.annotation.Nullable;
public class RegionFlagsListener extends AbstractListener {
/**
* Construct the listener.
*
* @param plugin an instance of WorldGuardPlugin
*/
public RegionFlagsListener(WorldGuardPlugin plugin) {
super(plugin);
}
@EventHandler(priority = EventPriority.LOW, ignoreCancelled = true)
public void onPlaceBlock(final PlaceBlockEvent event) {
if (!isRegionSupportEnabled(event.getWorld())) return; // Region support disabled
RegionQuery query = getPlugin().getRegionContainer().createQuery();
Block block;
if ((block = event.getCause().getFirstBlock()) != null) {
// ================================================================
// PISTONS flag
// ================================================================
if (Materials.isPistonBlock(block.getType())) {
event.filter(testState(query, DefaultFlag.PISTONS), false);
}
}
}
@EventHandler(priority = EventPriority.LOW, ignoreCancelled = true)
public void onBreakBlock(final BreakBlockEvent event) {
if (!isRegionSupportEnabled(event.getWorld())) return; // Region support disabled
WorldConfiguration config = getWorldConfig(event.getWorld());
RegionQuery query = getPlugin().getRegionContainer().createQuery();
Block block;
if ((block = event.getCause().getFirstBlock()) != null) {
// ================================================================
// PISTONS flag
// ================================================================
if (Materials.isPistonBlock(block.getType())) {
event.filter(testState(query, DefaultFlag.PISTONS), false);
}
}
Entity entity;
if ((entity = event.getCause().getFirstEntity()) != null) {
// ================================================================
// CREEPER_EXPLOSION flag
// ================================================================
if (entity instanceof Creeper) { // Creeper
event.filter(testState(query, DefaultFlag.CREEPER_EXPLOSION), config.explosionFlagCancellation);
}
// ================================================================
// ENDERDRAGON_BLOCK_DAMAGE flag
// ================================================================
if (entity instanceof EnderDragon) { // Enderdragon
event.filter(testState(query, DefaultFlag.ENDERDRAGON_BLOCK_DAMAGE), config.explosionFlagCancellation);
}
}
}
@EventHandler(priority = EventPriority.LOW, ignoreCancelled = true)
public void onSpawnEntity(final SpawnEntityEvent event) {
if (!isRegionSupportEnabled(event.getWorld())) return; // Region support disabled
RegionQuery query = getPlugin().getRegionContainer().createQuery();
// ================================================================
// EXP_DROPS flag
// ================================================================
if (event.getEffectiveType() == EntityType.EXPERIENCE_ORB) {
event.filter(testState(query, DefaultFlag.EXP_DROPS), false);
}
}
/**
* Create a new predicate to test a state flag for each location.
*
* @param query the query
* @param flag the flag
* @return a predicate
*/
private Predicate<Location> testState(final RegionQuery query, final StateFlag flag) {
return new Predicate<Location>() {
@Override
public boolean apply(@Nullable Location location) {
return query.testState(location, null, flag);
}
};
}
}

View File

@ -0,0 +1,427 @@
/*
* 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.google.common.base.Predicate;
import com.sk89q.worldguard.bukkit.RegionQuery;
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.block.BreakBlockEvent;
import com.sk89q.worldguard.bukkit.event.block.PlaceBlockEvent;
import com.sk89q.worldguard.bukkit.event.block.UseBlockEvent;
import com.sk89q.worldguard.bukkit.event.entity.DamageEntityEvent;
import com.sk89q.worldguard.bukkit.event.entity.DestroyEntityEvent;
import com.sk89q.worldguard.bukkit.event.entity.SpawnEntityEvent;
import com.sk89q.worldguard.bukkit.event.entity.UseEntityEvent;
import com.sk89q.worldguard.bukkit.permission.RegionPermissionModel;
import com.sk89q.worldguard.bukkit.util.DelayedRegionOverlapAssociation;
import com.sk89q.worldguard.bukkit.util.Entities;
import com.sk89q.worldguard.bukkit.util.Events;
import com.sk89q.worldguard.bukkit.util.Materials;
import com.sk89q.worldguard.bukkit.util.WGMetadata;
import com.sk89q.worldguard.domains.Association;
import com.sk89q.worldguard.protection.association.Associables;
import com.sk89q.worldguard.protection.association.RegionAssociable;
import com.sk89q.worldguard.protection.events.DisallowedPVPEvent;
import com.sk89q.worldguard.protection.flags.DefaultFlag;
import com.sk89q.worldguard.protection.flags.StateFlag.State;
import org.bukkit.ChatColor;
import org.bukkit.Location;
import org.bukkit.Material;
import org.bukkit.OfflinePlayer;
import org.bukkit.World;
import org.bukkit.block.Block;
import org.bukkit.entity.Entity;
import org.bukkit.entity.EntityType;
import org.bukkit.entity.Item;
import org.bukkit.entity.Player;
import org.bukkit.entity.Tameable;
import org.bukkit.event.EventHandler;
import org.bukkit.event.vehicle.VehicleExitEvent;
/**
* Handle events that need to be processed by region protection.
*/
public class RegionProtectionListener extends AbstractListener {
private static final String DENY_MESSAGE_KEY = "worldguard.region.lastMessage";
private static final String DISEMBARK_MESSAGE_KEY = "worldguard.region.disembarkMessage";
private static final int LAST_MESSAGE_DELAY = 500;
/**
* Construct the listener.
*
* @param plugin an instance of WorldGuardPlugin
*/
public RegionProtectionListener(WorldGuardPlugin plugin) {
super(plugin);
}
/**
* Tell a sender that s/he cannot do something 'here'.
*
* @param cause the cause
* @param location the location
* @param what what was done
*/
private void tellErrorMessage(Cause cause, Location location, String what) {
Object rootCause = cause.getRootCause();
if (rootCause instanceof Player) {
Player player = (Player) rootCause;
long now = System.currentTimeMillis();
Long lastTime = WGMetadata.getIfPresent(player, DENY_MESSAGE_KEY, Long.class);
if (lastTime == null || now - lastTime >= LAST_MESSAGE_DELAY) {
RegionQuery query = getPlugin().getRegionContainer().createQuery();
String message = query.queryValue(location, player, DefaultFlag.DENY_MESSAGE);
if (message != null) {
player.sendMessage(message.replace("%what%", what));
}
WGMetadata.put(player, DENY_MESSAGE_KEY, now);
}
}
}
/**
* Return whether the given cause is whitelist (should be ignored).
*
* @param cause the cause
* @return true if whitelisted
*/
private boolean isWhitelisted(Cause cause, World world) {
Object rootCause = cause.getRootCause();
if (rootCause instanceof Player) {
Player player = (Player) rootCause;
WorldConfiguration config = getWorldConfig(world);
if (config.fakePlayerBuildOverride && Entities.isFakePlayer(player)) {
return true;
}
return new RegionPermissionModel(getPlugin(), player).mayIgnoreRegionProtection(world);
} else {
return false;
}
}
private RegionAssociable createRegionAssociable(Cause cause) {
Object rootCause = cause.getRootCause();
if (rootCause instanceof Player) {
return getPlugin().wrapPlayer((Player) rootCause);
} else if (rootCause instanceof OfflinePlayer) {
return getPlugin().wrapOfflinePlayer((OfflinePlayer) rootCause);
} else if (rootCause instanceof Entity) {
RegionQuery query = getPlugin().getRegionContainer().createQuery();
return new DelayedRegionOverlapAssociation(query, ((Entity) rootCause).getLocation());
} else if (rootCause instanceof Block) {
RegionQuery query = getPlugin().getRegionContainer().createQuery();
return new DelayedRegionOverlapAssociation(query, ((Block) rootCause).getLocation());
} else {
return Associables.constant(Association.NON_MEMBER);
}
}
@EventHandler(ignoreCancelled = true)
public void onPlaceBlock(final PlaceBlockEvent event) {
if (!isRegionSupportEnabled(event.getWorld())) return; // Region support disabled
if (isWhitelisted(event.getCause(), event.getWorld())) return; // Whitelisted cause
final Material type = event.getEffectiveMaterial();
final RegionQuery query = getPlugin().getRegionContainer().createQuery();
final RegionAssociable associable = createRegionAssociable(event.getCause());
// Don't check liquid flow unless it's enabled
if (Materials.isLiquid(type) && !getWorldConfig(event.getWorld()).checkLiquidFlow) {
return;
}
event.filter(new Predicate<Location>() {
@Override
public boolean apply(Location target) {
boolean canPlace;
String what;
/* Flint and steel, fire charge, etc. */
if (type == Material.FIRE) {
canPlace = query.testBuild(target, associable, DefaultFlag.BLOCK_PLACE, DefaultFlag.LIGHTER);
what = "place fire";
/* Everything else */
} else {
canPlace = query.testBuild(target, associable, DefaultFlag.BLOCK_PLACE);
what = "place that block";
}
if (!canPlace) {
tellErrorMessage(event.getCause(), target, what);
return false;
}
return true;
}
});
}
@EventHandler(ignoreCancelled = true)
public void onBreakBlock(final BreakBlockEvent event) {
if (!isRegionSupportEnabled(event.getWorld())) return; // Region support disabled
if (isWhitelisted(event.getCause(), event.getWorld())) return; // Whitelisted cause
final RegionQuery query = getPlugin().getRegionContainer().createQuery();
if (!event.isCancelled()) {
final RegionAssociable associable = createRegionAssociable(event.getCause());
event.filter(new Predicate<Location>() {
@Override
public boolean apply(Location target) {
boolean canBreak;
String what;
/* TNT */
if (event.getCause().find(EntityType.PRIMED_TNT, EntityType.PRIMED_TNT) != null) {
canBreak = query.testBuild(target, associable, DefaultFlag.BLOCK_BREAK, DefaultFlag.TNT);
what = "dynamite blocks";
/* Everything else */
} else {
canBreak = query.testBuild(target, associable, DefaultFlag.BLOCK_BREAK);
what = "break that block";
}
if (!canBreak) {
tellErrorMessage(event.getCause(), target, what);
return false;
}
return true;
}
});
}
}
@EventHandler(ignoreCancelled = true)
public void onUseBlock(final UseBlockEvent event) {
if (!isRegionSupportEnabled(event.getWorld())) return; // Region support disabled
if (isWhitelisted(event.getCause(), event.getWorld())) return; // Whitelisted cause
final Material type = event.getEffectiveMaterial();
final RegionQuery query = getPlugin().getRegionContainer().createQuery();
final RegionAssociable associable = createRegionAssociable(event.getCause());
event.filter(new Predicate<Location>() {
@Override
public boolean apply(Location target) {
boolean canUse;
String what;
/* Inventory */
if (Materials.isInventoryBlock(type)) {
canUse = query.testBuild(target, associable, DefaultFlag.USE, DefaultFlag.CHEST_ACCESS);
what = "open that";
/* Beds */
} else if (type == Material.BED_BLOCK) {
canUse = query.testBuild(target, associable, DefaultFlag.USE, DefaultFlag.SLEEP);
what = "sleep";
/* TNT */
} else if (type == Material.TNT) {
canUse = query.testBuild(target, associable, DefaultFlag.TNT);
what = "use explosives";
/* Everything else */
} else {
canUse = query.testBuild(target, associable, DefaultFlag.USE);
what = "use that";
}
if (!canUse) {
tellErrorMessage(event.getCause(), target, what);
return false;
}
return true;
}
});
}
@EventHandler(ignoreCancelled = true)
public void onSpawnEntity(SpawnEntityEvent event) {
if (!isRegionSupportEnabled(event.getWorld())) return; // Region support disabled
if (isWhitelisted(event.getCause(), event.getWorld())) return; // Whitelisted cause
Location target = event.getTarget();
EntityType type = event.getEffectiveType();
RegionQuery query = getPlugin().getRegionContainer().createQuery();
RegionAssociable associable = createRegionAssociable(event.getCause());
boolean canSpawn;
String what;
/* Vehicles */
if (Entities.isVehicle(type)) {
canSpawn = query.testBuild(target, associable, DefaultFlag.PLACE_VEHICLE);
what = "place vehicles";
/* Item pickup */
} else if (event.getEntity() instanceof Item) {
canSpawn = query.testBuild(target, associable, DefaultFlag.ITEM_DROP);
what = "drop items";
/* Everything else */
} else {
canSpawn = query.testBuild(target, associable);
if (event.getEntity() instanceof Item) {
what = "drop items";
} else {
what = "place things";
}
}
if (!canSpawn) {
tellErrorMessage(event.getCause(), target, what);
event.setCancelled(true);
}
}
@EventHandler(ignoreCancelled = true)
public void onDestroyEntity(DestroyEntityEvent event) {
if (!isRegionSupportEnabled(event.getWorld())) return; // Region support disabled
if (isWhitelisted(event.getCause(), event.getWorld())) return; // Whitelisted cause
Location target = event.getTarget();
EntityType type = event.getEntity().getType();
RegionAssociable associable = createRegionAssociable(event.getCause());
RegionQuery query = getPlugin().getRegionContainer().createQuery();
boolean canDestroy;
String what;
/* Vehicles */
if (Entities.isVehicle(type)) {
canDestroy = query.testBuild(target, associable, DefaultFlag.DESTROY_VEHICLE);
what = "break vehicles";
/* Item pickup */
} else if (event.getEntity() instanceof Item) {
canDestroy = query.testBuild(target, associable, DefaultFlag.ITEM_PICKUP);
what = "pick up items";
/* Everything else */
} else {
canDestroy = query.testBuild(target, associable);
what = "break things";
}
if (!canDestroy) {
tellErrorMessage(event.getCause(), target, what);
event.setCancelled(true);
}
}
@EventHandler(ignoreCancelled = true)
public void onUseEntity(UseEntityEvent event) {
if (!isRegionSupportEnabled(event.getWorld())) return; // Region support disabled
if (isWhitelisted(event.getCause(), event.getWorld())) return; // Whitelisted cause
Location target = event.getTarget();
RegionAssociable associable = createRegionAssociable(event.getCause());
RegionQuery query = getPlugin().getRegionContainer().createQuery();
boolean canUse = query.testBuild(target, associable, DefaultFlag.USE);
String what = "use that";
if (!canUse) {
tellErrorMessage(event.getCause(), target, what);
event.setCancelled(true);
}
}
@EventHandler(ignoreCancelled = true)
public void onDamageEntity(DamageEntityEvent event) {
if (!isRegionSupportEnabled(event.getWorld())) return; // Region support disabled
if (isWhitelisted(event.getCause(), event.getWorld())) return; // Whitelisted cause
Location target = event.getTarget();
RegionAssociable associable = createRegionAssociable(event.getCause());
RegionQuery query = getPlugin().getRegionContainer().createQuery();
Player attacker;
boolean canDamage;
String what;
/* PVP */
if (event.getEntity() instanceof Player && (attacker = event.getCause().getFirstPlayer()) != null) {
Player defender = (Player) event.getEntity();
canDamage = query.testBuild(target, associable, DefaultFlag.PVP)
&& query.queryState(attacker.getLocation(), attacker, DefaultFlag.PVP) != State.DENY;
// Fire the disallow PVP event
if (!canDamage && Events.fireAndTestCancel(new DisallowedPVPEvent(attacker, defender, event.getOriginalEvent()))) {
canDamage = true;
}
what = "PvP";
/* Everything else */
} else {
canDamage = query.testBuild(target, associable, DefaultFlag.USE);
what = "hit that";
}
if (!canDamage) {
tellErrorMessage(event.getCause(), target, what);
event.setCancelled(true);
}
}
@EventHandler(ignoreCancelled = true)
public void onVehicleExit(VehicleExitEvent event) {
Entity vehicle = event.getVehicle();
Entity exited = event.getExited();
if (vehicle instanceof Tameable && exited instanceof Player) {
Player player = (Player) exited;
if (!isWhitelisted(Cause.create(player), vehicle.getWorld())) {
RegionQuery query = getPlugin().getRegionContainer().createQuery();
Location location = vehicle.getLocation();
if (!query.testBuild(location, player, DefaultFlag.USE)) {
long now = System.currentTimeMillis();
Long lastTime = WGMetadata.getIfPresent(player, DISEMBARK_MESSAGE_KEY, Long.class);
if (lastTime == null || now - lastTime >= LAST_MESSAGE_DELAY) {
player.sendMessage("" + ChatColor.GOLD + "Don't disembark here!" + ChatColor.GRAY + " You can't get back on.");
WGMetadata.put(player, DISEMBARK_MESSAGE_KEY, now);
}
event.setCancelled(true);
}
}
}
}
}

View File

@ -1,129 +1,132 @@
/*
* WorldGuard, a suite of tools for Minecraft
* Copyright (C) sk89q <http://www.sk89q.com>
* Copyright (C) WorldGuard team and contributors
*
* This program is free software: you can redistribute it and/or modify it
* under the terms of the GNU Lesser General Public License as published by the
* Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License
* for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package com.sk89q.worldguard.bukkit;
import org.bukkit.World;
import static com.sk89q.worldguard.bukkit.BukkitUtil.isBlockWater;
import static com.sk89q.worldguard.bukkit.BukkitUtil.setBlockToWater;
public final class SpongeUtil {
private SpongeUtil() {
}
/**
* Remove water around a sponge.
*
* @param plugin The plugin instace
* @param world The world the sponge isin
* @param ox The x coordinate of the 'sponge' block
* @param oy The y coordinate of the 'sponge' block
* @param oz The z coordinate of the 'sponge' block
*/
public static void clearSpongeWater(WorldGuardPlugin plugin, World world, int ox, int oy, int oz) {
ConfigurationManager cfg = plugin.getGlobalStateManager();
WorldConfiguration wcfg = cfg.get(world);
for (int cx = -wcfg.spongeRadius; cx <= wcfg.spongeRadius; cx++) {
for (int cy = -wcfg.spongeRadius; cy <= wcfg.spongeRadius; cy++) {
for (int cz = -wcfg.spongeRadius; cz <= wcfg.spongeRadius; cz++) {
if (isBlockWater(world, ox + cx, oy + cy, oz + cz)) {
world.getBlockAt(ox + cx, oy + cy, oz + cz).setTypeId(0);
}
}
}
}
}
/**
* Add water around a sponge.
*
* @param plugin The plugin instance
* @param world The world the sponge is located in
* @param ox The x coordinate of the 'sponge' block
* @param oy The y coordinate of the 'sponge' block
* @param oz The z coordinate of the 'sponge' block
*/
public static void addSpongeWater(WorldGuardPlugin plugin, World world, int ox, int oy, int oz) {
ConfigurationManager cfg = plugin.getGlobalStateManager();
WorldConfiguration wcfg = cfg.get(world);
// The negative x edge
int cx = ox - wcfg.spongeRadius - 1;
for (int cy = oy - wcfg.spongeRadius - 1; cy <= oy + wcfg.spongeRadius + 1; cy++) {
for (int cz = oz - wcfg.spongeRadius - 1; cz <= oz + wcfg.spongeRadius + 1; cz++) {
if (isBlockWater(world, cx, cy, cz)) {
setBlockToWater(world, cx + 1, cy, cz);
}
}
}
// The positive x edge
cx = ox + wcfg.spongeRadius + 1;
for (int cy = oy - wcfg.spongeRadius - 1; cy <= oy + wcfg.spongeRadius + 1; cy++) {
for (int cz = oz - wcfg.spongeRadius - 1; cz <= oz + wcfg.spongeRadius + 1; cz++) {
if (isBlockWater(world, cx, cy, cz)) {
setBlockToWater(world, cx - 1, cy, cz);
}
}
}
// The negative y edge
int cy = oy - wcfg.spongeRadius - 1;
for (cx = ox - wcfg.spongeRadius - 1; cx <= ox + wcfg.spongeRadius + 1; cx++) {
for (int cz = oz - wcfg.spongeRadius - 1; cz <= oz + wcfg.spongeRadius + 1; cz++) {
if (isBlockWater(world, cx, cy, cz)) {
setBlockToWater(world, cx, cy + 1, cz);
}
}
}
// The positive y edge
cy = oy + wcfg.spongeRadius + 1;
for (cx = ox - wcfg.spongeRadius - 1; cx <= ox + wcfg.spongeRadius + 1; cx++) {
for (int cz = oz - wcfg.spongeRadius - 1; cz <= oz + wcfg.spongeRadius + 1; cz++) {
if (isBlockWater(world, cx, cy, cz)) {
setBlockToWater(world, cx, cy - 1, cz);
}
}
}
// The negative z edge
int cz = oz - wcfg.spongeRadius - 1;
for (cx = ox - wcfg.spongeRadius - 1; cx <= ox + wcfg.spongeRadius + 1; cx++) {
for (cy = oy - wcfg.spongeRadius - 1; cy <= oy + wcfg.spongeRadius + 1; cy++) {
if (isBlockWater(world, cx, cy, cz)) {
setBlockToWater(world, cx, cy, cz + 1);
}
}
}
// The positive z edge
cz = oz + wcfg.spongeRadius + 1;
for (cx = ox - wcfg.spongeRadius - 1; cx <= ox + wcfg.spongeRadius + 1; cx++) {
for (cy = oy - wcfg.spongeRadius - 1; cy <= oy + wcfg.spongeRadius + 1; cy++) {
if (isBlockWater(world, cx, cy, cz)) {
setBlockToWater(world, cx, cy, cz - 1);
}
}
}
}
}
/*
* WorldGuard, a suite of tools for Minecraft
* Copyright (C) sk89q <http://www.sk89q.com>
* Copyright (C) WorldGuard team and contributors
*
* This program is free software: you can redistribute it and/or modify it
* under the terms of the GNU Lesser General Public License as published by the
* Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License
* for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package com.sk89q.worldguard.bukkit.listener;
import com.sk89q.worldguard.bukkit.ConfigurationManager;
import com.sk89q.worldguard.bukkit.WorldConfiguration;
import com.sk89q.worldguard.bukkit.WorldGuardPlugin;
import org.bukkit.World;
import static com.sk89q.worldguard.bukkit.BukkitUtil.isBlockWater;
import static com.sk89q.worldguard.bukkit.BukkitUtil.setBlockToWater;
public final class SpongeUtil {
private SpongeUtil() {
}
/**
* Remove water around a sponge.
*
* @param plugin The plugin instace
* @param world The world the sponge isin
* @param ox The x coordinate of the 'sponge' block
* @param oy The y coordinate of the 'sponge' block
* @param oz The z coordinate of the 'sponge' block
*/
public static void clearSpongeWater(WorldGuardPlugin plugin, World world, int ox, int oy, int oz) {
ConfigurationManager cfg = plugin.getGlobalStateManager();
WorldConfiguration wcfg = cfg.get(world);
for (int cx = -wcfg.spongeRadius; cx <= wcfg.spongeRadius; cx++) {
for (int cy = -wcfg.spongeRadius; cy <= wcfg.spongeRadius; cy++) {
for (int cz = -wcfg.spongeRadius; cz <= wcfg.spongeRadius; cz++) {
if (isBlockWater(world, ox + cx, oy + cy, oz + cz)) {
world.getBlockAt(ox + cx, oy + cy, oz + cz).setTypeId(0);
}
}
}
}
}
/**
* Add water around a sponge.
*
* @param plugin The plugin instance
* @param world The world the sponge is located in
* @param ox The x coordinate of the 'sponge' block
* @param oy The y coordinate of the 'sponge' block
* @param oz The z coordinate of the 'sponge' block
*/
public static void addSpongeWater(WorldGuardPlugin plugin, World world, int ox, int oy, int oz) {
ConfigurationManager cfg = plugin.getGlobalStateManager();
WorldConfiguration wcfg = cfg.get(world);
// The negative x edge
int cx = ox - wcfg.spongeRadius - 1;
for (int cy = oy - wcfg.spongeRadius - 1; cy <= oy + wcfg.spongeRadius + 1; cy++) {
for (int cz = oz - wcfg.spongeRadius - 1; cz <= oz + wcfg.spongeRadius + 1; cz++) {
if (isBlockWater(world, cx, cy, cz)) {
setBlockToWater(world, cx + 1, cy, cz);
}
}
}
// The positive x edge
cx = ox + wcfg.spongeRadius + 1;
for (int cy = oy - wcfg.spongeRadius - 1; cy <= oy + wcfg.spongeRadius + 1; cy++) {
for (int cz = oz - wcfg.spongeRadius - 1; cz <= oz + wcfg.spongeRadius + 1; cz++) {
if (isBlockWater(world, cx, cy, cz)) {
setBlockToWater(world, cx - 1, cy, cz);
}
}
}
// The negative y edge
int cy = oy - wcfg.spongeRadius - 1;
for (cx = ox - wcfg.spongeRadius - 1; cx <= ox + wcfg.spongeRadius + 1; cx++) {
for (int cz = oz - wcfg.spongeRadius - 1; cz <= oz + wcfg.spongeRadius + 1; cz++) {
if (isBlockWater(world, cx, cy, cz)) {
setBlockToWater(world, cx, cy + 1, cz);
}
}
}
// The positive y edge
cy = oy + wcfg.spongeRadius + 1;
for (cx = ox - wcfg.spongeRadius - 1; cx <= ox + wcfg.spongeRadius + 1; cx++) {
for (int cz = oz - wcfg.spongeRadius - 1; cz <= oz + wcfg.spongeRadius + 1; cz++) {
if (isBlockWater(world, cx, cy, cz)) {
setBlockToWater(world, cx, cy - 1, cz);
}
}
}
// The negative z edge
int cz = oz - wcfg.spongeRadius - 1;
for (cx = ox - wcfg.spongeRadius - 1; cx <= ox + wcfg.spongeRadius + 1; cx++) {
for (cy = oy - wcfg.spongeRadius - 1; cy <= oy + wcfg.spongeRadius + 1; cy++) {
if (isBlockWater(world, cx, cy, cz)) {
setBlockToWater(world, cx, cy, cz + 1);
}
}
}
// The positive z edge
cz = oz + wcfg.spongeRadius + 1;
for (cx = ox - wcfg.spongeRadius - 1; cx <= ox + wcfg.spongeRadius + 1; cx++) {
for (cy = oy - wcfg.spongeRadius - 1; cy <= oy + wcfg.spongeRadius + 1; cy++) {
if (isBlockWater(world, cx, cy, cz)) {
setBlockToWater(world, cx, cy, cz - 1);
}
}
}
}
}

View File

@ -17,10 +17,11 @@
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package com.sk89q.worldguard.bukkit;
package com.sk89q.worldguard.bukkit.listener;
import com.sk89q.commandbook.InfoComponent;
import com.sk89q.worldguard.LocalPlayer;
import com.sk89q.worldguard.bukkit.WorldGuardPlugin;
import com.sk89q.worldguard.protection.ApplicableRegionSet;
import com.sk89q.worldguard.protection.regions.ProtectedRegion;
import org.bukkit.entity.Player;
@ -43,8 +44,7 @@ public void onPlayerWhois(InfoComponent.PlayerWhoisEvent event) {
Player player = (Player) event.getPlayer();
LocalPlayer localPlayer = plugin.wrapPlayer(player);
if (plugin.getGlobalStateManager().get(player.getWorld()).useRegions) {
ApplicableRegionSet regions = plugin.getGlobalRegionManager()
.get(player.getWorld()).getApplicableRegions(player.getLocation());
ApplicableRegionSet regions = plugin.getRegionContainer().createQuery().getApplicableRegions(player.getLocation());
// Current regions
StringBuilder regionStr = new StringBuilder();

View File

@ -0,0 +1,122 @@
/*
* WorldGuard, a suite of tools for Minecraft
* Copyright (C) sk89q <http://www.sk89q.com>
* Copyright (C) WorldGuard team and contributors
*
* This program is free software: you can redistribute it and/or modify it
* under the terms of the GNU Lesser General Public License as published by the
* Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License
* for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package com.sk89q.worldguard.bukkit.listener;
import com.sk89q.worldguard.bukkit.ConfigurationManager;
import com.sk89q.worldguard.bukkit.WorldConfiguration;
import com.sk89q.worldguard.bukkit.WorldGuardPlugin;
import com.sk89q.worldguard.protection.flags.DefaultFlag;
import org.bukkit.World;
import org.bukkit.entity.Creeper;
import org.bukkit.entity.Entity;
import org.bukkit.entity.Hanging;
import org.bukkit.entity.ItemFrame;
import org.bukkit.entity.LivingEntity;
import org.bukkit.entity.Painting;
import org.bukkit.entity.Player;
import org.bukkit.entity.Projectile;
import org.bukkit.event.EventHandler;
import org.bukkit.event.EventPriority;
import org.bukkit.event.Listener;
import org.bukkit.event.hanging.HangingBreakByEntityEvent;
import org.bukkit.event.hanging.HangingBreakEvent;
import org.bukkit.event.hanging.HangingBreakEvent.RemoveCause;
import org.bukkit.projectiles.ProjectileSource;
/**
* Listener for painting related events.
*
* @author BangL <henno.rickowski@gmail.com>
*/
public class WorldGuardHangingListener implements Listener {
private WorldGuardPlugin plugin;
/**
* Construct the object;
*
* @param plugin The plugin instance
*/
public WorldGuardHangingListener(WorldGuardPlugin plugin) {
this.plugin = plugin;
}
/**
* Register events.
*/
public void registerEvents() {
plugin.getServer().getPluginManager().registerEvents(this, plugin);
}
@EventHandler(priority = EventPriority.HIGH, ignoreCancelled = true)
public void onHangingBreak(HangingBreakEvent event) {
Hanging hanging = event.getEntity();
World world = hanging.getWorld();
ConfigurationManager cfg = plugin.getGlobalStateManager();
WorldConfiguration wcfg = cfg.get(world);
if (event instanceof HangingBreakByEntityEvent) {
HangingBreakByEntityEvent entityEvent = (HangingBreakByEntityEvent) event;
Entity removerEntity = entityEvent.getRemover();
if (removerEntity instanceof Projectile) {
Projectile projectile = (Projectile) removerEntity;
ProjectileSource remover = projectile.getShooter();
removerEntity = (remover instanceof LivingEntity ? (LivingEntity) remover : null);
}
if (!(removerEntity instanceof Player)) {
if (removerEntity instanceof Creeper) {
if (wcfg.blockCreeperBlockDamage || wcfg.blockCreeperExplosions) {
event.setCancelled(true);
return;
}
if (wcfg.useRegions && !plugin.getGlobalRegionManager().allows(DefaultFlag.CREEPER_EXPLOSION, hanging.getLocation())) {
event.setCancelled(true);
return;
}
}
// this now covers dispensers as well, if removerEntity is null above,
// due to a non-LivingEntity ProjectileSource
if (hanging instanceof Painting
&& (wcfg.blockEntityPaintingDestroy
|| (wcfg.useRegions
&& !plugin.getGlobalRegionManager().allows(DefaultFlag.ENTITY_PAINTING_DESTROY, hanging.getLocation())))) {
event.setCancelled(true);
} else if (hanging instanceof ItemFrame
&& (wcfg.blockEntityItemFrameDestroy
|| (wcfg.useRegions
&& !plugin.getGlobalRegionManager().allows(DefaultFlag.ENTITY_ITEM_FRAME_DESTROY, hanging.getLocation())))) {
event.setCancelled(true);
}
}
} else {
// Explosions from mobs are not covered by HangingBreakByEntity
if (hanging instanceof Painting && wcfg.blockEntityPaintingDestroy
&& event.getCause() == RemoveCause.EXPLOSION) {
event.setCancelled(true);
} else if (hanging instanceof ItemFrame && wcfg.blockEntityItemFrameDestroy
&& event.getCause() == RemoveCause.EXPLOSION) {
event.setCancelled(true);
}
}
}
}

View File

@ -0,0 +1,675 @@
/*
* 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.worldedit.Vector;
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.WorldConfiguration;
import com.sk89q.worldguard.bukkit.WorldGuardPlugin;
import com.sk89q.worldguard.bukkit.listener.FlagStateManager.PlayerFlagState;
import com.sk89q.worldguard.protection.ApplicableRegionSet;
import com.sk89q.worldguard.protection.flags.DefaultFlag;
import com.sk89q.worldguard.protection.managers.RegionManager;
import com.sk89q.worldguard.protection.regions.ProtectedRegion;
import com.sk89q.worldguard.util.command.CommandFilter;
import org.bukkit.ChatColor;
import org.bukkit.GameMode;
import org.bukkit.Location;
import org.bukkit.World;
import org.bukkit.block.Block;
import org.bukkit.entity.Entity;
import org.bukkit.entity.Player;
import org.bukkit.event.EventHandler;
import org.bukkit.event.EventPriority;
import org.bukkit.event.Listener;
import org.bukkit.event.block.Action;
import org.bukkit.event.player.AsyncPlayerChatEvent;
import org.bukkit.event.player.PlayerCommandPreprocessEvent;
import org.bukkit.event.player.PlayerGameModeChangeEvent;
import org.bukkit.event.player.PlayerInteractEvent;
import org.bukkit.event.player.PlayerItemHeldEvent;
import org.bukkit.event.player.PlayerJoinEvent;
import org.bukkit.event.player.PlayerLoginEvent;
import org.bukkit.event.player.PlayerMoveEvent;
import org.bukkit.event.player.PlayerQuitEvent;
import org.bukkit.event.player.PlayerRespawnEvent;
import org.bukkit.event.player.PlayerTeleportEvent;
import org.bukkit.event.player.PlayerTeleportEvent.TeleportCause;
import org.bukkit.inventory.ItemStack;
import org.bukkit.plugin.PluginManager;
import java.util.Iterator;
import java.util.Set;
import java.util.logging.Level;
import java.util.logging.Logger;
import java.util.regex.Pattern;
/**
* Handles all events thrown in relation to a player.
*/
public class WorldGuardPlayerListener implements Listener {
private static final Logger log = Logger.getLogger(WorldGuardPlayerListener.class.getCanonicalName());
private Pattern opPattern = Pattern.compile("^/op(?:\\s.*)?$", Pattern.CASE_INSENSITIVE);
private WorldGuardPlugin plugin;
/**
* Construct the object;
*
* @param plugin
*/
public WorldGuardPlayerListener(WorldGuardPlugin plugin) {
this.plugin = plugin;
}
/**
* Register events.
*/
public void registerEvents() {
final PluginManager pm = plugin.getServer().getPluginManager();
pm.registerEvents(this, plugin);
if (plugin.getGlobalStateManager().usePlayerMove) {
pm.registerEvents(new PlayerMoveHandler(), plugin);
}
}
// unsure if anyone actually started using this yet, but just in case...
@Deprecated
public static boolean checkMove(WorldGuardPlugin plugin, Player player, World world, Location from, Location to) {
return checkMove(plugin, player, from, to); // drop world since it used to be mishandled
}
/**
* Handles movement related events, including changing gamemode, sending
* greeting/farewell messages, etc.
* A reference to WorldGuardPlugin is required to keep this method static
* although WGBukkit.getPlugin() may be used.
* @return true if the movement should not be allowed
*/
public static boolean checkMove(WorldGuardPlugin plugin, Player player, Location from, Location to) {
PlayerFlagState state = plugin.getFlagStateManager().getState(player);
//Flush states in multiworld scenario
if (state.lastWorld != null && !state.lastWorld.equals(to.getWorld())) {
plugin.getFlagStateManager().forget(player);
state = plugin.getFlagStateManager().getState(player);
}
World world = from.getWorld();
World toWorld = to.getWorld();
LocalPlayer localPlayer = plugin.wrapPlayer(player);
boolean hasBypass = plugin.getGlobalRegionManager().hasBypass(player, world);
boolean hasRemoteBypass;
if (world.equals(toWorld)) {
hasRemoteBypass = hasBypass;
} else {
hasRemoteBypass = plugin.getGlobalRegionManager().hasBypass(player, toWorld);
}
RegionManager mgr = plugin.getGlobalRegionManager().get(toWorld);
if (mgr == null) {
return false;
}
Vector pt = new Vector(to.getBlockX(), to.getBlockY(), to.getBlockZ());
ApplicableRegionSet set = mgr.getApplicableRegions(pt);
/*
// check if region is full
// get the lowest number of allowed members in any region
boolean regionFull = false;
String maxPlayerMessage = null;
if (!hasBypass) {
for (ProtectedRegion region : set) {
if (region instanceof GlobalProtectedRegion) {
continue; // global region can't have a max
}
// get the max for just this region
Integer maxPlayers = region.getFlag(DefaultFlag.MAX_PLAYERS);
if (maxPlayers == null) {
continue;
}
int occupantCount = 0;
for(Player occupant : world.getPlayers()) {
// each player in this region counts as one toward the max of just this region
// A person with bypass doesn't count as an occupant of the region
if (!occupant.equals(player) && !plugin.getGlobalRegionManager().hasBypass(occupant, world)) {
if (region.contains(BukkitUtil.toVector(occupant.getLocation()))) {
if (++occupantCount >= maxPlayers) {
regionFull = true;
maxPlayerMessage = region.getFlag(DefaultFlag.MAX_PLAYERS_MESSAGE);
// At least one region in the set is full, we are going to use this message because it
// was the first one we detected as full. In reality we should check them all and then
// resolve the message from full regions, but that is probably a lot laggier (and this
// is already pretty laggy. In practice, we can't really control which one we get first
// right here.
break;
}
}
}
}
}
}
*/
boolean entryAllowed = set.allows(DefaultFlag.ENTRY, localPlayer);
if (!hasRemoteBypass && (!entryAllowed /*|| regionFull*/)) {
String message = /*maxPlayerMessage != null ? maxPlayerMessage :*/ "You are not permitted to enter this area.";
player.sendMessage(ChatColor.DARK_RED + message);
return true;
}
// Have to set this state
if (state.lastExitAllowed == null) {
state.lastExitAllowed = plugin.getRegionContainer().createQuery().getApplicableRegions(from)
.allows(DefaultFlag.EXIT, localPlayer);
}
boolean exitAllowed = set.allows(DefaultFlag.EXIT, localPlayer);
if (!hasBypass && exitAllowed && !state.lastExitAllowed) {
player.sendMessage(ChatColor.DARK_RED + "You are not permitted to leave this area.");
return true;
}
// WorldGuardRegionMoveEvent event = new WorldGuardRegionMoveEvent(plugin, player, state, set, from, to);
// Bukkit.getPluginManager().callEvent(event);
String greeting = set.getFlag(DefaultFlag.GREET_MESSAGE);//, localPlayer);
String farewell = set.getFlag(DefaultFlag.FAREWELL_MESSAGE);//, localPlayer);
Boolean notifyEnter = set.getFlag(DefaultFlag.NOTIFY_ENTER);//, localPlayer);
Boolean notifyLeave = set.getFlag(DefaultFlag.NOTIFY_LEAVE);//, localPlayer);
GameMode gameMode = set.getFlag(DefaultFlag.GAME_MODE);
if (state.lastFarewell != null && (farewell == null
|| !state.lastFarewell.equals(farewell))) {
String replacedFarewell = plugin.replaceMacros(
player, BukkitUtil.replaceColorMacros(state.lastFarewell));
player.sendMessage(replacedFarewell.replaceAll("\\\\n", "\n").split("\\n"));
}
if (greeting != null && (state.lastGreeting == null
|| !state.lastGreeting.equals(greeting))) {
String replacedGreeting = plugin.replaceMacros(
player, BukkitUtil.replaceColorMacros(greeting));
player.sendMessage(replacedGreeting.replaceAll("\\\\n", "\n").split("\\n"));
}
if ((notifyLeave == null || !notifyLeave)
&& state.notifiedForLeave != null && state.notifiedForLeave) {
plugin.broadcastNotification(ChatColor.GRAY + "WG: "
+ ChatColor.LIGHT_PURPLE + player.getName()
+ ChatColor.GOLD + " left NOTIFY region");
}
if (notifyEnter != null && notifyEnter && (state.notifiedForEnter == null
|| !state.notifiedForEnter)) {
StringBuilder regionList = new StringBuilder();
for (ProtectedRegion region : set) {
if (regionList.length() != 0) {
regionList.append(", ");
}
regionList.append(region.getId());
}
plugin.broadcastNotification(ChatColor.GRAY + "WG: "
+ ChatColor.LIGHT_PURPLE + player.getName()
+ ChatColor.GOLD + " entered NOTIFY region: "
+ ChatColor.WHITE
+ regionList);
}
if (!hasBypass && gameMode != null) {
if (player.getGameMode() != gameMode) {
state.lastGameMode = player.getGameMode();
player.setGameMode(gameMode);
} else if (state.lastGameMode == null) {
state.lastGameMode = player.getServer().getDefaultGameMode();
}
} else {
if (state.lastGameMode != null) {
GameMode mode = state.lastGameMode;
state.lastGameMode = null;
player.setGameMode(mode);
}
}
state.lastGreeting = greeting;
state.lastFarewell = farewell;
state.notifiedForEnter = notifyEnter;
state.notifiedForLeave = notifyLeave;
state.lastExitAllowed = exitAllowed;
state.lastWorld = to.getWorld();
state.lastBlockX = to.getBlockX();
state.lastBlockY = to.getBlockY();
state.lastBlockZ = to.getBlockZ();
return false;
}
class PlayerMoveHandler implements Listener {
@EventHandler(priority = EventPriority.HIGH)
public void onPlayerMove(PlayerMoveEvent event) {
final Player player = event.getPlayer();
World world = player.getWorld();
ConfigurationManager cfg = plugin.getGlobalStateManager();
WorldConfiguration wcfg = cfg.get(world);
if (wcfg.useRegions) {
// Did we move a block?
if (event.getFrom().getBlockX() != event.getTo().getBlockX()
|| event.getFrom().getBlockY() != event.getTo().getBlockY()
|| event.getFrom().getBlockZ() != event.getTo().getBlockZ()) {
boolean result = checkMove(plugin, player, event.getFrom(), event.getTo());
if (result) {
final Location newLoc = event.getFrom();
newLoc.setX(newLoc.getBlockX() + 0.5);
newLoc.setY(newLoc.getBlockY());
newLoc.setZ(newLoc.getBlockZ() + 0.5);
event.setTo(newLoc);
final Entity vehicle = player.getVehicle();
if (vehicle != null) {
vehicle.eject();
vehicle.teleport(newLoc);
player.teleport(newLoc);
vehicle.setPassenger(player);
}
}
}
}
}
}
@EventHandler
public void onPlayerGameModeChange(PlayerGameModeChangeEvent event) {
Player player = event.getPlayer();
WorldConfiguration wcfg = plugin.getGlobalStateManager().get(player.getWorld());
if (wcfg.useRegions && !plugin.getGlobalRegionManager().hasBypass(player, player.getWorld())) {
GameMode gameMode = plugin.getRegionContainer().createQuery().getApplicableRegions(player.getLocation()).getFlag(DefaultFlag.GAME_MODE);
if (plugin.getFlagStateManager().getState(player).lastGameMode != null
&& gameMode != null && event.getNewGameMode() != gameMode) {
event.setCancelled(true);
}
}
}
@EventHandler
public void onPlayerJoin(PlayerJoinEvent event) {
Player player = event.getPlayer();
World world = player.getWorld();
ConfigurationManager cfg = plugin.getGlobalStateManager();
WorldConfiguration wcfg = cfg.get(world);
if (cfg.activityHaltToggle) {
player.sendMessage(ChatColor.YELLOW
+ "Intensive server activity has been HALTED.");
int removed = 0;
for (Entity entity : world.getEntities()) {
if (BukkitUtil.isIntensiveEntity(entity)) {
entity.remove();
removed++;
}
}
if (removed > 10) {
log.info("Halt-Act: " + removed + " entities (>10) auto-removed from "
+ player.getWorld().toString());
}
}
if (wcfg.fireSpreadDisableToggle) {
player.sendMessage(ChatColor.YELLOW
+ "Fire spread is currently globally disabled for this world.");
}
if (!cfg.hasCommandBookGodMode() && cfg.autoGodMode && (plugin.inGroup(player, "wg-invincible")
|| plugin.hasPermission(player, "worldguard.auto-invincible"))) {
log.log(Level.INFO, "Enabled auto-god mode for " + player.getName());
cfg.enableGodMode(player);
}
if (plugin.inGroup(player, "wg-amphibious")) {
log.log(Level.INFO, "Enabled no-drowning mode for " + player.getName() + " (player is in group 'wg-amphibious')");
cfg.enableAmphibiousMode(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();
}
}
@EventHandler(ignoreCancelled = true)
public void onPlayerChat(AsyncPlayerChatEvent event) {
Player player = event.getPlayer();
WorldConfiguration wcfg = plugin.getGlobalStateManager().get(player.getWorld());
if (wcfg.useRegions) {
if (!plugin.getGlobalRegionManager().allows(DefaultFlag.SEND_CHAT, player.getLocation())) {
player.sendMessage(ChatColor.RED + "You don't have permission to chat in this region!");
event.setCancelled(true);
return;
}
for (Iterator<Player> i = event.getRecipients().iterator(); i.hasNext();) {
if (!plugin.getGlobalRegionManager().allows(DefaultFlag.RECEIVE_CHAT, i.next().getLocation())) {
i.remove();
}
}
if (event.getRecipients().size() == 0) {
event.setCancelled(true);
}
}
}
@EventHandler(ignoreCancelled = true)
public void onPlayerLogin(PlayerLoginEvent event) {
Player player = event.getPlayer();
ConfigurationManager cfg = plugin.getGlobalStateManager();
String hostKey = cfg.hostKeys.get(player.getName().toLowerCase());
if (hostKey != null) {
String hostname = event.getHostname();
int colonIndex = hostname.indexOf(':');
if (colonIndex != -1) {
hostname = hostname.substring(0, colonIndex);
}
if (!hostname.equals(hostKey)) {
event.disallow(PlayerLoginEvent.Result.KICK_OTHER,
"You did not join with the valid host key!");
log.warning("WorldGuard host key check: " +
player.getName() + " joined with '" + hostname +
"' but '" + hostKey + "' was expected. Kicked!");
return;
}
}
if (cfg.deopOnJoin) {
player.setOp(false);
}
}
@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();
World world = player.getWorld();
if (event.getAction() == Action.RIGHT_CLICK_BLOCK) {
handleBlockRightClick(event);
} else if (event.getAction() == Action.PHYSICAL) {
handlePhysicalInteract(event);
}
ConfigurationManager cfg = plugin.getGlobalStateManager();
WorldConfiguration wcfg = cfg.get(world);
if (wcfg.removeInfiniteStacks
&& !plugin.hasPermission(player, "worldguard.override.infinite-stack")) {
int slot = player.getInventory().getHeldItemSlot();
ItemStack heldItem = player.getInventory().getItem(slot);
if (heldItem != null && heldItem.getAmount() < 0) {
player.getInventory().setItem(slot, null);
player.sendMessage(ChatColor.RED + "Infinite stack removed.");
}
}
}
/**
* Called when a player right clicks a block.
*
* @param event Thrown event
*/
private void handleBlockRightClick(PlayerInteractEvent event) {
if (event.isCancelled()) {
return;
}
Block block = event.getClickedBlock();
World world = block.getWorld();
int type = block.getTypeId();
Player player = event.getPlayer();
ItemStack item = player.getItemInHand();
ConfigurationManager cfg = plugin.getGlobalStateManager();
WorldConfiguration wcfg = cfg.get(world);
// Infinite stack removal
if ((type == BlockID.CHEST
|| type == BlockID.JUKEBOX
|| type == BlockID.DISPENSER
|| type == BlockID.FURNACE
|| type == BlockID.BURNING_FURNACE
|| type == BlockID.BREWING_STAND
|| type == BlockID.ENCHANTMENT_TABLE)
&& wcfg.removeInfiniteStacks
&& !plugin.hasPermission(player, "worldguard.override.infinite-stack")) {
for (int slot = 0; slot < 40; slot++) {
ItemStack heldItem = player.getInventory().getItem(slot);
if (heldItem != null && heldItem.getAmount() < 0) {
player.getInventory().setItem(slot, null);
player.sendMessage(ChatColor.RED + "Infinite stack in slot #" + slot + " removed.");
}
}
}
if (wcfg.useRegions) {
Block placedIn = block.getRelative(event.getBlockFace());
ApplicableRegionSet set = plugin.getRegionContainer().createQuery().getApplicableRegions(block.getLocation());
ApplicableRegionSet placedInSet = plugin.getRegionContainer().createQuery().getApplicableRegions(placedIn.getLocation());
LocalPlayer localPlayer = plugin.wrapPlayer(player);
if (item.getTypeId() == wcfg.regionWand && plugin.hasPermission(player, "worldguard.region.wand")) {
if (set.size() > 0) {
player.sendMessage(ChatColor.YELLOW + "Can you build? "
+ (set.canBuild(localPlayer) ? "Yes" : "No"));
StringBuilder str = new StringBuilder();
for (Iterator<ProtectedRegion> it = set.iterator(); it.hasNext();) {
str.append(it.next().getId());
if (it.hasNext()) {
str.append(", ");
}
}
player.sendMessage(ChatColor.YELLOW + "Applicable regions: " + str.toString());
} else {
player.sendMessage(ChatColor.YELLOW + "WorldGuard: No defined regions here!");
}
event.setCancelled(true);
}
}
}
/**
* Called when a player steps on a pressure plate or tramples crops.
*
* @param event Thrown event
*/
private void handlePhysicalInteract(PlayerInteractEvent event) {
if (event.isCancelled()) return;
Player player = event.getPlayer();
Block block = event.getClickedBlock(); //not actually clicked but whatever
int type = block.getTypeId();
World world = player.getWorld();
ConfigurationManager cfg = plugin.getGlobalStateManager();
WorldConfiguration wcfg = cfg.get(world);
if (block.getTypeId() == BlockID.SOIL && wcfg.disablePlayerCropTrampling) {
event.setCancelled(true);
return;
}
}
@EventHandler(priority = EventPriority.HIGHEST)
public void onPlayerRespawn(PlayerRespawnEvent event) {
Player player = event.getPlayer();
Location location = player.getLocation();
ConfigurationManager cfg = plugin.getGlobalStateManager();
WorldConfiguration wcfg = cfg.get(player.getWorld());
if (wcfg.useRegions) {
ApplicableRegionSet set = plugin.getRegionContainer().createQuery().getApplicableRegions(location);
LocalPlayer localPlayer = plugin.wrapPlayer(player);
com.sk89q.worldedit.Location spawn = set.getFlag(DefaultFlag.SPAWN_LOC, localPlayer);
if (spawn != null) {
event.setRespawnLocation(com.sk89q.worldedit.bukkit.BukkitUtil.toLocation(spawn));
}
}
}
@EventHandler(priority = EventPriority.HIGH)
public void onItemHeldChange(PlayerItemHeldEvent event) {
Player player = event.getPlayer();
ConfigurationManager cfg = plugin.getGlobalStateManager();
WorldConfiguration wcfg = cfg.get(player.getWorld());
if (wcfg.removeInfiniteStacks
&& !plugin.hasPermission(player, "worldguard.override.infinite-stack")) {
int newSlot = event.getNewSlot();
ItemStack heldItem = player.getInventory().getItem(newSlot);
if (heldItem != null && heldItem.getAmount() < 0) {
player.getInventory().setItem(newSlot, null);
player.sendMessage(ChatColor.RED + "Infinite stack removed.");
}
}
}
@EventHandler(priority= EventPriority.LOW, ignoreCancelled = true)
public void onPlayerTeleport(PlayerTeleportEvent event) {
World world = event.getFrom().getWorld();
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());
if (cfg.usePlayerTeleports) {
boolean result = checkMove(plugin, event.getPlayer(), event.getFrom(), event.getTo());
if (result) {
event.setCancelled(true);
return;
}
}
if (event.getCause() == TeleportCause.ENDER_PEARL) {
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.");
event.setCancelled(true);
return;
}
}
}
}
@EventHandler(priority = EventPriority.LOWEST, ignoreCancelled = true)
public void onPlayerCommandPreprocess(PlayerCommandPreprocessEvent event) {
Player player = event.getPlayer();
LocalPlayer localPlayer = plugin.wrapPlayer(player);
World world = player.getWorld();
ConfigurationManager cfg = plugin.getGlobalStateManager();
WorldConfiguration wcfg = cfg.get(world);
if (wcfg.useRegions && !plugin.getGlobalRegionManager().hasBypass(player, world)) {
ApplicableRegionSet set = plugin.getRegionContainer().createQuery().getApplicableRegions(player.getLocation());
Set<String> allowedCommands = set.getFlag(DefaultFlag.ALLOWED_CMDS, localPlayer);
Set<String> blockedCommands = set.getFlag(DefaultFlag.BLOCKED_CMDS, localPlayer);
CommandFilter test = new CommandFilter(allowedCommands, blockedCommands);
if (!test.apply(event.getMessage())) {
player.sendMessage(ChatColor.RED + event.getMessage() + " is not allowed in this area.");
event.setCancelled(true);
return;
}
}
if (cfg.blockInGameOp) {
if (opPattern.matcher(event.getMessage()).matches()) {
player.sendMessage(ChatColor.RED + "/op can only be used in console (as set by a WG setting).");
event.setCancelled(true);
return;
}
}
}
}

View File

@ -17,8 +17,9 @@
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package com.sk89q.worldguard.bukkit;
package com.sk89q.worldguard.bukkit.listener;
import com.sk89q.worldguard.bukkit.WorldGuardPlugin;
import org.bukkit.event.EventHandler;
import org.bukkit.event.Listener;
import org.bukkit.event.server.PluginDisableEvent;

View File

@ -1,110 +1,75 @@
/*
* WorldGuard, a suite of tools for Minecraft
* Copyright (C) sk89q <http://www.sk89q.com>
* Copyright (C) WorldGuard team and contributors
*
* This program is free software: you can redistribute it and/or modify it
* under the terms of the GNU Lesser General Public License as published by the
* Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License
* for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package com.sk89q.worldguard.bukkit;
import static com.sk89q.worldguard.bukkit.BukkitUtil.toVector;
import org.bukkit.ChatColor;
import org.bukkit.World;
import org.bukkit.entity.Entity;
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.VehicleDestroyEvent;
import org.bukkit.event.vehicle.VehicleMoveEvent;
import com.sk89q.worldedit.Vector;
import com.sk89q.worldguard.LocalPlayer;
import com.sk89q.worldguard.protection.ApplicableRegionSet;
import com.sk89q.worldguard.protection.flags.DefaultFlag;
import com.sk89q.worldguard.protection.managers.RegionManager;
public class WorldGuardVehicleListener implements Listener {
private WorldGuardPlugin plugin;
/**
* Construct the object;
*
* @param plugin
*/
public WorldGuardVehicleListener(WorldGuardPlugin plugin) {
this.plugin = plugin;
}
/**
* Register events.
*/
public void registerEvents() {
plugin.getServer().getPluginManager().registerEvents(this, plugin);
}
@EventHandler
public void onVehicleDestroy(VehicleDestroyEvent event) {
Vehicle vehicle = event.getVehicle();
Entity destroyer = event.getAttacker();
if (!(destroyer instanceof Player)) return; // don't care
Player player = (Player) destroyer;
World world = vehicle.getWorld();
ConfigurationManager cfg = plugin.getGlobalStateManager();
WorldConfiguration wcfg = cfg.get(world);
if (wcfg.useRegions) {
Vector pt = toVector(vehicle.getLocation());
RegionManager mgr = plugin.getGlobalRegionManager().get(world);
ApplicableRegionSet set = mgr.getApplicableRegions(pt);
LocalPlayer localPlayer = plugin.wrapPlayer(player);
if (!plugin.getGlobalRegionManager().hasBypass(player, world)
&& !set.canBuild(localPlayer)
&& !set.allows(DefaultFlag.DESTROY_VEHICLE, localPlayer)) {
player.sendMessage(ChatColor.DARK_RED + "You don't have permission to destroy vehicles here.");
event.setCancelled(true);
return;
}
}
}
@EventHandler
public void onVehicleMove(VehicleMoveEvent event) {
Vehicle vehicle = event.getVehicle();
if (vehicle.getPassenger() == null
|| !(vehicle.getPassenger() instanceof Player)) return;
Player player = (Player) vehicle.getPassenger();
World world = vehicle.getWorld();
ConfigurationManager cfg = plugin.getGlobalStateManager();
WorldConfiguration wcfg = cfg.get(world);
if (wcfg.useRegions) {
// Did we move a block?
if (event.getFrom().getBlockX() != event.getTo().getBlockX()
|| event.getFrom().getBlockY() != event.getTo().getBlockY()
|| event.getFrom().getBlockZ() != event.getTo().getBlockZ()) {
boolean result = WorldGuardPlayerListener.checkMove(plugin, player, event.getFrom(), event.getTo());
if (result) {
vehicle.setVelocity(new org.bukkit.util.Vector(0,0,0));
vehicle.teleport(event.getFrom());
}
}
}
}
}
/*
* WorldGuard, a suite of tools for Minecraft
* Copyright (C) sk89q <http://www.sk89q.com>
* Copyright (C) WorldGuard team and contributors
*
* This program is free software: you can redistribute it and/or modify it
* under the terms of the GNU Lesser General Public License as published by the
* Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License
* for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package com.sk89q.worldguard.bukkit.listener;
import com.sk89q.worldguard.bukkit.ConfigurationManager;
import com.sk89q.worldguard.bukkit.WorldConfiguration;
import com.sk89q.worldguard.bukkit.WorldGuardPlugin;
import 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;
public class WorldGuardVehicleListener implements Listener {
private WorldGuardPlugin plugin;
/**
* Construct the object;
*
* @param plugin
*/
public WorldGuardVehicleListener(WorldGuardPlugin plugin) {
this.plugin = plugin;
}
/**
* Register events.
*/
public void registerEvents() {
plugin.getServer().getPluginManager().registerEvents(this, plugin);
}
@EventHandler
public void onVehicleMove(VehicleMoveEvent event) {
Vehicle vehicle = event.getVehicle();
if (vehicle.getPassenger() == null
|| !(vehicle.getPassenger() instanceof Player)) return;
Player player = (Player) vehicle.getPassenger();
World world = vehicle.getWorld();
ConfigurationManager cfg = plugin.getGlobalStateManager();
WorldConfiguration wcfg = cfg.get(world);
if (wcfg.useRegions) {
// Did we move a block?
if (event.getFrom().getBlockX() != event.getTo().getBlockX()
|| event.getFrom().getBlockY() != event.getTo().getBlockY()
|| event.getFrom().getBlockZ() != event.getTo().getBlockZ()) {
boolean result = WorldGuardPlayerListener.checkMove(plugin, player, event.getFrom(), event.getTo());
if (result) {
vehicle.setVelocity(new org.bukkit.util.Vector(0,0,0));
vehicle.teleport(event.getFrom());
}
}
}
}
}

View File

@ -1,111 +1,108 @@
/*
* WorldGuard, a suite of tools for Minecraft
* Copyright (C) sk89q <http://www.sk89q.com>
* Copyright (C) WorldGuard team and contributors
*
* This program is free software: you can redistribute it and/or modify it
* under the terms of the GNU Lesser General Public License as published by the
* Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License
* for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package com.sk89q.worldguard.bukkit;
import static com.sk89q.worldguard.bukkit.BukkitUtil.toVector;
import org.bukkit.Location;
import org.bukkit.event.EventHandler;
import org.bukkit.event.EventPriority;
import org.bukkit.event.Listener;
import org.bukkit.event.weather.LightningStrikeEvent;
import org.bukkit.event.weather.ThunderChangeEvent;
import org.bukkit.event.weather.WeatherChangeEvent;
import com.sk89q.worldedit.Vector;
import com.sk89q.worldguard.protection.ApplicableRegionSet;
import com.sk89q.worldguard.protection.flags.DefaultFlag;
import com.sk89q.worldguard.protection.managers.RegionManager;
public class WorldGuardWeatherListener implements Listener {
/**
* Plugin.
*/
private WorldGuardPlugin plugin;
/**
* Construct the object;
*
* @param plugin The plugin instance
*/
public WorldGuardWeatherListener(WorldGuardPlugin plugin) {
this.plugin = plugin;
}
public void registerEvents() {
plugin.getServer().getPluginManager().registerEvents(this, plugin);
}
@EventHandler(priority = EventPriority.HIGH, ignoreCancelled = true)
public void onWeatherChange(WeatherChangeEvent event) {
ConfigurationManager cfg = plugin.getGlobalStateManager();
WorldConfiguration wcfg = cfg.get(event.getWorld());
if (event.toWeatherState()) {
if (wcfg.disableWeather) {
event.setCancelled(true);
}
} else {
if (!wcfg.disableWeather && wcfg.alwaysRaining) {
event.setCancelled(true);
}
}
}
@EventHandler(priority = EventPriority.HIGH, ignoreCancelled = true)
public void onThunderChange(ThunderChangeEvent event) {
ConfigurationManager cfg = plugin.getGlobalStateManager();
WorldConfiguration wcfg = cfg.get(event.getWorld());
if (event.toThunderState()) {
if (wcfg.disableThunder) {
event.setCancelled(true);
}
} else {
if (!wcfg.disableWeather && wcfg.alwaysThundering) {
event.setCancelled(true);
}
}
}
@EventHandler(priority = EventPriority.HIGH, ignoreCancelled = true)
public void onLightningStrike(LightningStrikeEvent event) {
ConfigurationManager cfg = plugin.getGlobalStateManager();
WorldConfiguration wcfg = cfg.get(event.getWorld());
if (wcfg.disallowedLightningBlocks.size() > 0) {
int targetId = event.getLightning().getLocation().getBlock().getTypeId();
if (wcfg.disallowedLightningBlocks.contains(targetId)) {
event.setCancelled(true);
}
}
Location loc = event.getLightning().getLocation();
if (wcfg.useRegions) {
Vector pt = toVector(loc);
RegionManager mgr = plugin.getGlobalRegionManager().get(loc.getWorld());
ApplicableRegionSet set = mgr.getApplicableRegions(pt);
if (!set.allows(DefaultFlag.LIGHTNING)) {
event.setCancelled(true);
}
}
}
}
/*
* WorldGuard, a suite of tools for Minecraft
* Copyright (C) sk89q <http://www.sk89q.com>
* Copyright (C) WorldGuard team and contributors
*
* This program is free software: you can redistribute it and/or modify it
* under the terms of the GNU Lesser General Public License as published by the
* Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License
* for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package com.sk89q.worldguard.bukkit.listener;
import com.sk89q.worldguard.bukkit.ConfigurationManager;
import com.sk89q.worldguard.bukkit.WorldConfiguration;
import com.sk89q.worldguard.bukkit.WorldGuardPlugin;
import com.sk89q.worldguard.protection.ApplicableRegionSet;
import com.sk89q.worldguard.protection.flags.DefaultFlag;
import org.bukkit.Location;
import org.bukkit.event.EventHandler;
import org.bukkit.event.EventPriority;
import org.bukkit.event.Listener;
import org.bukkit.event.weather.LightningStrikeEvent;
import org.bukkit.event.weather.ThunderChangeEvent;
import org.bukkit.event.weather.WeatherChangeEvent;
public class WorldGuardWeatherListener implements Listener {
/**
* Plugin.
*/
private WorldGuardPlugin plugin;
/**
* Construct the object;
*
* @param plugin The plugin instance
*/
public WorldGuardWeatherListener(WorldGuardPlugin plugin) {
this.plugin = plugin;
}
public void registerEvents() {
plugin.getServer().getPluginManager().registerEvents(this, plugin);
}
@EventHandler(priority = EventPriority.HIGH, ignoreCancelled = true)
public void onWeatherChange(WeatherChangeEvent event) {
ConfigurationManager cfg = plugin.getGlobalStateManager();
WorldConfiguration wcfg = cfg.get(event.getWorld());
if (event.toWeatherState()) {
if (wcfg.disableWeather) {
event.setCancelled(true);
}
} else {
if (!wcfg.disableWeather && wcfg.alwaysRaining) {
event.setCancelled(true);
}
}
}
@EventHandler(priority = EventPriority.HIGH, ignoreCancelled = true)
public void onThunderChange(ThunderChangeEvent event) {
ConfigurationManager cfg = plugin.getGlobalStateManager();
WorldConfiguration wcfg = cfg.get(event.getWorld());
if (event.toThunderState()) {
if (wcfg.disableThunder) {
event.setCancelled(true);
}
} else {
if (!wcfg.disableWeather && wcfg.alwaysThundering) {
event.setCancelled(true);
}
}
}
@EventHandler(priority = EventPriority.HIGH, ignoreCancelled = true)
public void onLightningStrike(LightningStrikeEvent event) {
ConfigurationManager cfg = plugin.getGlobalStateManager();
WorldConfiguration wcfg = cfg.get(event.getWorld());
if (wcfg.disallowedLightningBlocks.size() > 0) {
int targetId = event.getLightning().getLocation().getBlock().getTypeId();
if (wcfg.disallowedLightningBlocks.contains(targetId)) {
event.setCancelled(true);
}
}
Location loc = event.getLightning().getLocation();
if (wcfg.useRegions) {
ApplicableRegionSet set = plugin.getRegionContainer().createQuery().getApplicableRegions(loc);
if (!set.allows(DefaultFlag.LIGHTNING)) {
event.setCancelled(true);
}
}
}
}

View File

@ -1,97 +1,103 @@
/*
* WorldGuard, a suite of tools for Minecraft
* Copyright (C) sk89q <http://www.sk89q.com>
* Copyright (C) WorldGuard team and contributors
*
* This program is free software: you can redistribute it and/or modify it
* under the terms of the GNU Lesser General Public License as published by the
* Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License
* for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package com.sk89q.worldguard.bukkit;
import org.bukkit.World;
import org.bukkit.entity.Entity;
import org.bukkit.event.EventHandler;
import org.bukkit.event.Listener;
import org.bukkit.event.world.ChunkLoadEvent;
import org.bukkit.event.world.WorldLoadEvent;
public class WorldGuardWorldListener implements Listener {
private WorldGuardPlugin plugin;
/**
* Construct the object;
*
* @param plugin The plugin instance
*/
public WorldGuardWorldListener(WorldGuardPlugin plugin) {
this.plugin = plugin;
}
/**
* Register events.
*/
public void registerEvents() {
plugin.getServer().getPluginManager().registerEvents(this, plugin);
}
@EventHandler
public void onChunkLoad(ChunkLoadEvent event) {
ConfigurationManager cfg = plugin.getGlobalStateManager();
if (cfg.activityHaltToggle) {
int removed = 0;
for (Entity entity : event.getChunk().getEntities()) {
if (BukkitUtil.isIntensiveEntity(entity)) {
entity.remove();
removed++;
}
}
if (removed > 50) {
plugin.getLogger().info("Halt-Act: " + removed + " entities (>50) auto-removed from "
+ event.getChunk().toString());
}
}
}
@EventHandler
public void onWorldLoad(WorldLoadEvent event) {
initWorld(event.getWorld());
}
/**
* Initialize the settings for the specified world
* @see WorldConfiguration#alwaysRaining
* @see WorldConfiguration#disableWeather
* @see WorldConfiguration#alwaysThundering
* @see WorldConfiguration#disableThunder
* @param world The specified world
*/
public void initWorld(World world) {
ConfigurationManager cfg = plugin.getGlobalStateManager();
WorldConfiguration wcfg = cfg.get(world);
if (wcfg.alwaysRaining && !wcfg.disableWeather) {
world.setStorm(true);
} else if (wcfg.disableWeather && !wcfg.alwaysRaining) {
world.setStorm(false);
}
if (wcfg.alwaysThundering && !wcfg.disableThunder) {
world.setThundering(true);
} else if (wcfg.disableThunder && !wcfg.alwaysThundering) {
world.setStorm(false);
}
}
}
/*
* 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 org.bukkit.World;
import org.bukkit.entity.Entity;
import org.bukkit.event.EventHandler;
import org.bukkit.event.Listener;
import org.bukkit.event.world.ChunkLoadEvent;
import org.bukkit.event.world.WorldLoadEvent;
import java.util.logging.Logger;
public class WorldGuardWorldListener implements Listener {
private static final Logger log = Logger.getLogger(WorldGuardWorldListener.class.getCanonicalName());
private WorldGuardPlugin plugin;
/**
* Construct the object;
*
* @param plugin The plugin instance
*/
public WorldGuardWorldListener(WorldGuardPlugin plugin) {
this.plugin = plugin;
}
/**
* Register events.
*/
public void registerEvents() {
plugin.getServer().getPluginManager().registerEvents(this, plugin);
}
@EventHandler
public void onChunkLoad(ChunkLoadEvent event) {
ConfigurationManager cfg = plugin.getGlobalStateManager();
if (cfg.activityHaltToggle) {
int removed = 0;
for (Entity entity : event.getChunk().getEntities()) {
if (BukkitUtil.isIntensiveEntity(entity)) {
entity.remove();
removed++;
}
}
if (removed > 50) {
log.info("Halt-Act: " + removed + " entities (>50) auto-removed from " + event.getChunk().toString());
}
}
}
@EventHandler
public void onWorldLoad(WorldLoadEvent event) {
initWorld(event.getWorld());
}
/**
* Initialize the settings for the specified world
* @see WorldConfiguration#alwaysRaining
* @see WorldConfiguration#disableWeather
* @see WorldConfiguration#alwaysThundering
* @see WorldConfiguration#disableThunder
* @param world The specified world
*/
public void initWorld(World world) {
ConfigurationManager cfg = plugin.getGlobalStateManager();
WorldConfiguration wcfg = cfg.get(world);
if (wcfg.alwaysRaining && !wcfg.disableWeather) {
world.setStorm(true);
} else if (wcfg.disableWeather && !wcfg.alwaysRaining) {
world.setStorm(false);
}
if (wcfg.alwaysThundering && !wcfg.disableThunder) {
world.setThundering(true);
} else if (wcfg.disableThunder && !wcfg.alwaysThundering) {
world.setStorm(false);
}
}
}

View File

@ -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.bukkit.listener;
import com.sk89q.worldguard.bukkit.WorldConfiguration;
import com.sk89q.worldguard.bukkit.WorldGuardPlugin;
import com.sk89q.worldguard.bukkit.event.entity.SpawnEntityEvent;
import org.bukkit.entity.EntityType;
import org.bukkit.event.EventHandler;
import org.bukkit.event.EventPriority;
public class WorldRulesListener extends AbstractListener {
/**
* Construct the listener.
*
* @param plugin an instance of WorldGuardPlugin
*/
public WorldRulesListener(WorldGuardPlugin plugin) {
super(plugin);
}
@EventHandler(priority = EventPriority.LOWEST, ignoreCancelled = true)
public void onSpawnEntity(final SpawnEntityEvent event) {
WorldConfiguration config = getWorldConfig(event.getWorld());
// ================================================================
// EXP_DROPS flag
// ================================================================
if (event.getEffectiveType() == EntityType.EXPERIENCE_ORB) {
if (config.disableExpDrops) {
event.setCancelled(true);
}
}
}
}

View File

@ -0,0 +1,67 @@
/*
* 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.debounce;
import com.google.common.cache.Cache;
import com.google.common.cache.CacheBuilder;
import com.google.common.cache.CacheLoader;
import com.sk89q.worldguard.bukkit.util.Events;
import org.bukkit.event.Cancellable;
import org.bukkit.event.Event;
import java.util.concurrent.TimeUnit;
public class AbstractEventDebounce<K> {
private final Cache<K, Entry> cache;
AbstractEventDebounce(int debounceTime) {
cache = CacheBuilder.newBuilder()
.maximumSize(1000)
.expireAfterWrite(debounceTime, TimeUnit.MILLISECONDS)
.concurrencyLevel(2)
.build(new CacheLoader<K, Entry>() {
@Override
public Entry load(K key) throws Exception {
return new Entry();
}
});
}
protected <T extends Event & Cancellable> void debounce(K key, Cancellable originalEvent, T firedEvent) {
Entry entry = cache.getUnchecked(key);
if (entry.cancelled != null) {
if (entry.cancelled) {
originalEvent.setCancelled(true);
}
} else {
boolean cancelled = Events.fireAndTestCancel(firedEvent);
if (cancelled) {
originalEvent.setCancelled(true);
}
entry.cancelled = cancelled;
}
}
private static class Entry {
private Boolean cancelled;
}
}

View File

@ -0,0 +1,73 @@
/*
* 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.debounce;
import com.sk89q.worldguard.bukkit.listener.debounce.BlockEntityEventDebounce.Key;
import org.bukkit.Material;
import org.bukkit.block.Block;
import org.bukkit.entity.Entity;
import org.bukkit.event.Cancellable;
import org.bukkit.event.Event;
public class BlockEntityEventDebounce extends AbstractEventDebounce<Key> {
public BlockEntityEventDebounce(int debounceTime) {
super(debounceTime);
}
public <T extends Event & Cancellable> void debounce(Block block, Entity entity, Cancellable originalEvent, T firedEvent) {
super.debounce(new Key(block, entity), originalEvent, firedEvent);
}
protected static class Key {
private final Block block;
private final Material blockMaterial;
private final Entity entity;
private Key(Block block, Entity entity) {
this.block = block;
this.blockMaterial = block.getType();
this.entity = entity;
}
@Override
public boolean equals(Object o) {
if (this == o) return true;
if (o == null || getClass() != o.getClass()) return false;
Key key = (Key) o;
if (!block.equals(key.block)) return false;
if (blockMaterial != key.blockMaterial) return false;
if (!entity.equals(key.entity)) return false;
return true;
}
@Override
public int hashCode() {
int result = block.hashCode();
result = 31 * result + blockMaterial.hashCode();
result = 31 * result + entity.hashCode();
return result;
}
}
}

View File

@ -0,0 +1,67 @@
/*
* 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.debounce;
import com.sk89q.worldguard.bukkit.listener.debounce.EntityEntityEventDebounce.Key;
import org.bukkit.entity.Entity;
import org.bukkit.event.Cancellable;
import org.bukkit.event.Event;
public class EntityEntityEventDebounce extends AbstractEventDebounce<Key> {
public EntityEntityEventDebounce(int debounceTime) {
super(debounceTime);
}
public <T extends Event & Cancellable> void debounce(Entity source, Entity target, Cancellable originalEvent, T firedEvent) {
super.debounce(new Key(source, target), originalEvent, firedEvent);
}
protected static class Key {
private final Entity source;
private final Entity target;
public Key(Entity source, Entity target) {
this.source = source;
this.target = target;
}
@Override
public boolean equals(Object o) {
if (this == o) return true;
if (o == null || getClass() != o.getClass()) return false;
Key key = (Key) o;
if (!source.equals(key.source)) return false;
if (!target.equals(key.target)) return false;
return true;
}
@Override
public int hashCode() {
int result = source.hashCode();
result = 31 * result + target.hashCode();
return result;
}
}
}

View File

@ -17,8 +17,9 @@
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package com.sk89q.worldguard.bukkit;
package com.sk89q.worldguard.bukkit.permission;
import com.sk89q.worldguard.bukkit.WorldGuardPlugin;
import org.bukkit.command.CommandSender;
import com.sk89q.worldguard.internal.PermissionModel;

View File

@ -17,14 +17,15 @@
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package com.sk89q.worldguard.bukkit;
import org.bukkit.command.CommandSender;
import org.bukkit.entity.Player;
package com.sk89q.worldguard.bukkit.permission;
import com.sk89q.worldguard.LocalPlayer;
import com.sk89q.worldguard.bukkit.WorldGuardPlugin;
import com.sk89q.worldguard.protection.flags.Flag;
import com.sk89q.worldguard.protection.regions.ProtectedRegion;
import org.bukkit.World;
import org.bukkit.command.CommandSender;
import org.bukkit.entity.Player;
/**
* Used for querying region-related permissions.
@ -34,6 +35,10 @@ public class RegionPermissionModel extends AbstractPermissionModel {
public RegionPermissionModel(WorldGuardPlugin plugin, CommandSender sender) {
super(plugin, sender);
}
public boolean mayIgnoreRegionProtection(World world) {
return hasPluginPermission("region.bypass." + world.getName());
}
public boolean mayForceLoadRegions() {
return hasPluginPermission("region.load");
@ -42,10 +47,14 @@ public boolean mayForceLoadRegions() {
public boolean mayForceSaveRegions() {
return hasPluginPermission("region.save");
}
public boolean mayMigrateRegionStore() {
return hasPluginPermission("region.migratedb");
}
public boolean mayMigrateRegionNames() {
return hasPluginPermission("region.migrateuuid");
}
public boolean mayDefine() {
return hasPluginPermission("region.define");
@ -114,6 +123,22 @@ public boolean maySetFlag(ProtectedRegion region, Flag<?> flag) {
return hasPatternPermission(
"flag.flags." + flag.getName().toLowerCase(), region);
}
public boolean mayAddMembers(ProtectedRegion region) {
return hasPatternPermission("addmember", region);
}
public boolean mayAddOwners(ProtectedRegion region) {
return hasPatternPermission("addowner", region);
}
public boolean mayRemoveMembers(ProtectedRegion region) {
return hasPatternPermission("removemember", region);
}
public boolean mayRemoveOwners(ProtectedRegion region) {
return hasPatternPermission("removeowner", region);
}
/**
* Checks to see if the given sender has permission to modify the given region

View File

@ -0,0 +1,35 @@
/*
* WorldGuard, a suite of tools for Minecraft
* Copyright (C) sk89q <http://www.sk89q.com>
* Copyright (C) WorldGuard team and contributors
*
* This program is free software: you can redistribute it and/or modify it
* under the terms of the GNU Lesser General Public License as published by the
* Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License
* for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package com.sk89q.worldguard.bukkit.util;
import com.google.common.base.Function;
import org.bukkit.block.Block;
import org.bukkit.block.BlockState;
import javax.annotation.Nullable;
public class BlockStateAsBlockFunction implements Function<BlockState, Block> {
@Override
public Block apply(@Nullable BlockState blockState) {
return blockState != null ? blockState.getBlock() : null;
}
}

View File

@ -17,17 +17,18 @@
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package com.sk89q.worldguard.internal;
package com.sk89q.worldguard.bukkit.util;
import org.bukkit.block.Block;
import org.bukkit.block.Hopper;
import org.bukkit.material.Attachable;
import org.bukkit.material.Bed;
import org.bukkit.material.MaterialData;
import javax.annotation.Nullable;
import java.util.Arrays;
import java.util.Collections;
import java.util.List;
/**
* Block related utility methods.
* Utility methods to deal with blocks.
*/
public final class Blocks {
@ -35,21 +36,25 @@ private Blocks() {
}
/**
* Get the block that this block attaches to.
* Get a list of connected blocks to the given block, not including
* the given block.
*
* @param block the block to check
* @return the block attached to or null
* @param block the block
* @return a list of connected blocks, not including the given block
*/
@Nullable
public static Block getAttachesTo(Block block) {
public static List<Block> getConnected(Block block) {
MaterialData data = block.getState().getData();
if (data instanceof Attachable) {
Attachable attachable = (Attachable) data;
return block.getRelative(attachable.getAttachedFace());
if (data instanceof Bed) {
Bed bed = (Bed) data;
if (bed.isHeadOfBed()) {
return Arrays.asList(block.getRelative(bed.getFacing().getOppositeFace()));
} else {
return Arrays.asList(block.getRelative(bed.getFacing()));
}
} else {
return Collections.emptyList();
}
return null;
}
}

View File

@ -0,0 +1,75 @@
/*
* WorldGuard, a suite of tools for Minecraft
* Copyright (C) sk89q <http://www.sk89q.com>
* Copyright (C) WorldGuard team and contributors
*
* This program is free software: you can redistribute it and/or modify it
* under the terms of the GNU Lesser General Public License as published by the
* Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License
* for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package com.sk89q.worldguard.bukkit.util;
import com.sk89q.worldguard.bukkit.RegionQuery;
import com.sk89q.worldguard.domains.Association;
import com.sk89q.worldguard.protection.ApplicableRegionSet;
import com.sk89q.worldguard.protection.association.RegionAssociable;
import com.sk89q.worldguard.protection.regions.ProtectedRegion;
import org.bukkit.Location;
import javax.annotation.Nullable;
import java.util.Set;
import static com.google.common.base.Preconditions.checkNotNull;
/**
* Determines that the association to a region is {@code OWNER} if the input
* region is in a set of source regions.
*
* <p>This class only performs a spatial query if its
* {@link #getAssociation(ProtectedRegion)} method is called.</p>
*/
public class DelayedRegionOverlapAssociation implements RegionAssociable {
private final RegionQuery query;
private final Location location;
@Nullable
private Set<ProtectedRegion> source;
/**
* Create a new instance.
*
* @param query the query
* @param location the location
*/
public DelayedRegionOverlapAssociation(RegionQuery query, Location location) {
checkNotNull(query);
checkNotNull(location);
this.query = query;
this.location = location;
}
@Override
public Association getAssociation(ProtectedRegion region) {
if (source == null) {
ApplicableRegionSet result = query.getApplicableRegions(location);
source = result.getRegions();
}
if (source.contains(region)) {
return Association.OWNER;
} else {
return Association.NON_MEMBER;
}
}
}

View File

@ -0,0 +1,128 @@
/*
* WorldGuard, a suite of tools for Minecraft
* Copyright (C) sk89q <http://www.sk89q.com>
* Copyright (C) WorldGuard team and contributors
*
* This program is free software: you can redistribute it and/or modify it
* under the terms of the GNU Lesser General Public License as published by the
* Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License
* for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package com.sk89q.worldguard.bukkit.util;
import org.bukkit.entity.Entity;
import org.bukkit.entity.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.minecart.ExplosiveMinecart;
import org.bukkit.projectiles.ProjectileSource;
import javax.annotation.Nullable;
public final class Entities {
private Entities() {
}
/**
* Test whether the given entity is tameable and tamed.
*
* @param entity the entity, or null
* @return true if tamed
*/
public static boolean isTamed(@Nullable Entity entity) {
return entity instanceof Tameable && ((Tameable) entity).isTamed();
}
/**
* Return if the given entity type is TNT-based.
*
* @param entity the entity
* @return true if TNT based
*/
public static boolean isTNTBased(Entity entity) {
return entity instanceof TNTPrimed || entity instanceof ExplosiveMinecart;
}
/**
* Return if the given entity type is a fireball
* (not including wither skulls).
*
* @param type the type
* @return true if a fireball
*/
public static boolean isFireball(EntityType type) {
return type == EntityType.FIREBALL || type == EntityType.SMALL_FIREBALL;
}
/**
* Test whether the given entity type is a vehicle type.
*
* @param type the type
* @return true if the type is a vehicle type
*/
public static boolean isVehicle(EntityType type) {
return type == EntityType.BOAT
|| isMinecart(type);
}
/**
* Test whether the given entity type is a Minecart type.
*
* @param type the type
* @return true if the type is a Minecart type
*/
public static boolean isMinecart(EntityType type) {
return type == EntityType.MINECART
|| type == EntityType.MINECART_CHEST
|| type == EntityType.MINECART_COMMAND
|| type == EntityType.MINECART_FURNACE
|| type == EntityType.MINECART_HOPPER
|| type == EntityType.MINECART_MOB_SPAWNER
|| type == EntityType.MINECART_TNT;
}
/**
* Get the underlying shooter of a projectile if one exists.
*
* @param entity the entity
* @return the shooter
*/
public static Entity getShooter(Entity entity) {
while (entity instanceof Projectile) {
Projectile projectile = (Projectile) entity;
ProjectileSource remover = projectile.getShooter();
if (remover instanceof Entity && remover != entity) {
entity = (Entity) remover;
} else {
return entity;
}
}
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) == ']';
}
}

View File

@ -0,0 +1,77 @@
/*
* WorldGuard, a suite of tools for Minecraft
* Copyright (C) sk89q <http://www.sk89q.com>
* Copyright (C) WorldGuard team and contributors
*
* This program is free software: you can redistribute it and/or modify it
* under the terms of the GNU Lesser General Public License as published by the
* Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License
* for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package com.sk89q.worldguard.bukkit.util;
import org.bukkit.entity.Entity;
import org.bukkit.entity.LivingEntity;
import org.bukkit.event.entity.EntityDamageEvent.DamageCause;
/**
* Utility methods to deal with event-related enums in Bukkit.
*/
public final class EventEnums {
private EventEnums() {
}
/**
* Return whether the given damage cause is fire-reltaed.
*
* @param cause the cause
* @return true if fire related
*/
public static boolean isFireCause(DamageCause cause) {
return cause == DamageCause.FIRE || cause == DamageCause.FIRE_TICK;
}
/**
* Return whether the given cause is an explosion.
*
* @param cause the cause
* @return true if it is an explosion cuase
*/
public static boolean isExplosionCause(DamageCause cause) {
return cause == DamageCause.BLOCK_EXPLOSION || cause == DamageCause.ENTITY_EXPLOSION;
}
/**
* Restore the statistic associated with the given cause. For example,
* for the {@link DamageCause#DROWNING} cause, the entity would have its
* air level set to its maximum.
*
* @param entity the entity
* @param cause the cuase
*/
public static void restoreStatistic(Entity entity, DamageCause cause) {
if (cause == DamageCause.DROWNING && entity instanceof LivingEntity) {
LivingEntity living = (LivingEntity) entity;
living.setRemainingAir(living.getMaximumAir());
}
if (isFireCause(cause)) {
entity.setFireTicks(0);
}
if (cause == DamageCause.LAVA) {
entity.setFireTicks(0);
}
}
}

View File

@ -17,8 +17,9 @@
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package com.sk89q.worldguard.internal;
package com.sk89q.worldguard.bukkit.util;
import com.sk89q.worldguard.bukkit.event.BulkEvent;
import org.bukkit.Bukkit;
import org.bukkit.event.Cancellable;
import org.bukkit.event.Event;
@ -34,8 +35,20 @@ private Events() {
}
/**
* Fire the {@code eventToFire} if {@code original} has not been cancelled
* and cancel the original if the fired event is cancelled.
* Fire the {@code eventToFire} and return whether the event was cancelled.
*
* @param eventToFire the event to fire
* @param <T> an event that can be fired and is cancellable
* @return true if the event was cancelled
*/
public static <T extends Event & Cancellable> boolean fireAndTestCancel( T eventToFire) {
Bukkit.getServer().getPluginManager().callEvent(eventToFire);
return eventToFire.isCancelled();
}
/**
* Fire the {@code eventToFire} and cancel the original if the fired event
* is cancelled.
*
* @param original the original event to potentially cancel
* @param eventToFire the event to fire to consider cancelling the original event
@ -43,20 +56,18 @@ private Events() {
* @return true if the event was fired and it caused the original event to be cancelled
*/
public static <T extends Event & Cancellable> boolean fireToCancel(Cancellable original, T eventToFire) {
if (!original.isCancelled()) {
Bukkit.getServer().getPluginManager().callEvent(eventToFire);
if (eventToFire.isCancelled()) {
original.setCancelled(true);
return true;
}
Bukkit.getServer().getPluginManager().callEvent(eventToFire);
if (eventToFire.isCancelled()) {
original.setCancelled(true);
return true;
}
return false;
}
/**
* Fire the {@code eventToFire} if {@code original}
* and cancel the original if the fired event is cancelled.
* Fire the {@code eventToFire} and cancel the original if the fired event
* is cancelled.
*
* @param original the original event to potentially cancel
* @param eventToFire the event to fire to consider cancelling the original event
@ -73,4 +84,23 @@ public static <T extends Event & Cancellable> boolean fireItemEventToCancel(Play
return false;
}
/**
* Fire the {@code eventToFire} and cancel the original if the fired event
* is <strong>explicitly</strong> cancelled.
*
* @param original the original event to potentially cancel
* @param eventToFire the event to fire to consider cancelling the original event
* @param <T> an event that can be fired and is cancellable
* @return true if the event was fired and it caused the original event to be cancelled
*/
public static <T extends Event & Cancellable & BulkEvent> boolean fireBulkEventToCancel(Cancellable original, T eventToFire) {
Bukkit.getServer().getPluginManager().callEvent(eventToFire);
if (eventToFire.isExplicitlyCancelled()) {
original.setCancelled(true);
return true;
}
return false;
}
}

View File

@ -17,14 +17,14 @@
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package com.sk89q.worldguard.bukkit;
import java.util.logging.Handler;
import java.util.logging.LogRecord;
package com.sk89q.worldguard.bukkit.util;
import org.bukkit.ChatColor;
import org.bukkit.command.CommandSender;
import java.util.logging.Handler;
import java.util.logging.LogRecord;
/**
* Sends all logger messages to a player.
*

View File

@ -0,0 +1,609 @@
/*
* WorldGuard, a suite of tools for Minecraft
* Copyright (C) sk89q <http://www.sk89q.com>
* Copyright (C) WorldGuard team and contributors
*
* This program is free software: you can redistribute it and/or modify it
* under the terms of the GNU Lesser General Public License as published by the
* Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License
* for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package com.sk89q.worldguard.bukkit.util;
import com.google.common.collect.BiMap;
import com.google.common.collect.HashBiMap;
import org.bukkit.DyeColor;
import org.bukkit.Material;
import org.bukkit.entity.EntityType;
import org.bukkit.material.Dye;
import org.bukkit.material.MaterialData;
import javax.annotation.Nullable;
import java.util.HashMap;
import java.util.Map;
/**
* Material utility class.
*/
public final class Materials {
private static final int MODIFIED_ON_CLICK = 1;
private static final int MODIFIES_BLOCKS = 2;
private static final BiMap<EntityType, Material> ENTITY_ITEMS = HashBiMap.create();
private static final Map<Material, Integer> MATERIAL_FLAGS = new HashMap<Material, Integer>();
static {
ENTITY_ITEMS.put(EntityType.PAINTING, Material.PAINTING);
ENTITY_ITEMS.put(EntityType.ARROW, Material.ARROW);
ENTITY_ITEMS.put(EntityType.SNOWBALL, Material.SNOW_BALL);
ENTITY_ITEMS.put(EntityType.FIREBALL, Material.FIREBALL);
ENTITY_ITEMS.put(EntityType.SMALL_FIREBALL, Material.FIREWORK_CHARGE);
ENTITY_ITEMS.put(EntityType.ENDER_PEARL, Material.ENDER_PEARL);
ENTITY_ITEMS.put(EntityType.THROWN_EXP_BOTTLE, Material.EXP_BOTTLE);
ENTITY_ITEMS.put(EntityType.ITEM_FRAME, Material.ITEM_FRAME);
ENTITY_ITEMS.put(EntityType.PRIMED_TNT, Material.TNT);
ENTITY_ITEMS.put(EntityType.FIREWORK, Material.FIREWORK);
ENTITY_ITEMS.put(EntityType.MINECART_COMMAND, Material.COMMAND_MINECART);
ENTITY_ITEMS.put(EntityType.BOAT, Material.BOAT);
ENTITY_ITEMS.put(EntityType.MINECART, Material.MINECART);
ENTITY_ITEMS.put(EntityType.MINECART_CHEST, Material.STORAGE_MINECART);
ENTITY_ITEMS.put(EntityType.MINECART_FURNACE, Material.POWERED_MINECART);
ENTITY_ITEMS.put(EntityType.MINECART_TNT, Material.EXPLOSIVE_MINECART);
ENTITY_ITEMS.put(EntityType.MINECART_HOPPER, Material.HOPPER_MINECART);
ENTITY_ITEMS.put(EntityType.SPLASH_POTION, Material.POTION);
ENTITY_ITEMS.put(EntityType.EGG, Material.EGG);
MATERIAL_FLAGS.put(Material.AIR, 0);
MATERIAL_FLAGS.put(Material.STONE, 0);
MATERIAL_FLAGS.put(Material.GRASS, 0);
MATERIAL_FLAGS.put(Material.DIRT, 0);
MATERIAL_FLAGS.put(Material.COBBLESTONE, 0);
MATERIAL_FLAGS.put(Material.WOOD, 0);
MATERIAL_FLAGS.put(Material.SAPLING, 0);
MATERIAL_FLAGS.put(Material.BEDROCK, 0);
MATERIAL_FLAGS.put(Material.WATER, 0);
MATERIAL_FLAGS.put(Material.STATIONARY_WATER, 0);
MATERIAL_FLAGS.put(Material.LAVA, 0);
MATERIAL_FLAGS.put(Material.STATIONARY_LAVA, 0);
MATERIAL_FLAGS.put(Material.SAND, 0);
MATERIAL_FLAGS.put(Material.GRAVEL, 0);
MATERIAL_FLAGS.put(Material.GOLD_ORE, 0);
MATERIAL_FLAGS.put(Material.IRON_ORE, 0);
MATERIAL_FLAGS.put(Material.COAL_ORE, 0);
MATERIAL_FLAGS.put(Material.LOG, 0);
MATERIAL_FLAGS.put(Material.LEAVES, 0);
MATERIAL_FLAGS.put(Material.SPONGE, 0);
MATERIAL_FLAGS.put(Material.GLASS, 0);
MATERIAL_FLAGS.put(Material.LAPIS_ORE, 0);
MATERIAL_FLAGS.put(Material.LAPIS_BLOCK, 0);
MATERIAL_FLAGS.put(Material.DISPENSER, MODIFIED_ON_CLICK);
MATERIAL_FLAGS.put(Material.SANDSTONE, 0);
MATERIAL_FLAGS.put(Material.NOTE_BLOCK, MODIFIED_ON_CLICK);
MATERIAL_FLAGS.put(Material.BED_BLOCK, MODIFIED_ON_CLICK);
MATERIAL_FLAGS.put(Material.POWERED_RAIL, 0);
MATERIAL_FLAGS.put(Material.DETECTOR_RAIL, 0);
MATERIAL_FLAGS.put(Material.PISTON_STICKY_BASE, 0);
MATERIAL_FLAGS.put(Material.WEB, 0);
MATERIAL_FLAGS.put(Material.LONG_GRASS, 0);
MATERIAL_FLAGS.put(Material.DEAD_BUSH, 0);
MATERIAL_FLAGS.put(Material.PISTON_BASE, 0);
MATERIAL_FLAGS.put(Material.PISTON_EXTENSION, 0);
MATERIAL_FLAGS.put(Material.WOOL, 0);
MATERIAL_FLAGS.put(Material.PISTON_MOVING_PIECE, 0);
MATERIAL_FLAGS.put(Material.YELLOW_FLOWER, 0);
MATERIAL_FLAGS.put(Material.RED_ROSE, 0);
MATERIAL_FLAGS.put(Material.BROWN_MUSHROOM, 0);
MATERIAL_FLAGS.put(Material.RED_MUSHROOM, 0);
MATERIAL_FLAGS.put(Material.GOLD_BLOCK, 0);
MATERIAL_FLAGS.put(Material.IRON_BLOCK, 0);
MATERIAL_FLAGS.put(Material.DOUBLE_STEP, 0);
MATERIAL_FLAGS.put(Material.STEP, 0);
MATERIAL_FLAGS.put(Material.BRICK, 0);
MATERIAL_FLAGS.put(Material.TNT, MODIFIED_ON_CLICK);
MATERIAL_FLAGS.put(Material.BOOKSHELF, 0);
MATERIAL_FLAGS.put(Material.MOSSY_COBBLESTONE, 0);
MATERIAL_FLAGS.put(Material.OBSIDIAN, 0);
MATERIAL_FLAGS.put(Material.TORCH, 0);
MATERIAL_FLAGS.put(Material.FIRE, 0);
MATERIAL_FLAGS.put(Material.MOB_SPAWNER, 0);
MATERIAL_FLAGS.put(Material.WOOD_STAIRS, 0);
MATERIAL_FLAGS.put(Material.CHEST, MODIFIED_ON_CLICK);
MATERIAL_FLAGS.put(Material.REDSTONE_WIRE, 0);
MATERIAL_FLAGS.put(Material.DIAMOND_ORE, 0);
MATERIAL_FLAGS.put(Material.DIAMOND_BLOCK, 0);
MATERIAL_FLAGS.put(Material.WORKBENCH, 0);
MATERIAL_FLAGS.put(Material.CROPS, 0);
MATERIAL_FLAGS.put(Material.SOIL, 0);
MATERIAL_FLAGS.put(Material.FURNACE, MODIFIED_ON_CLICK);
MATERIAL_FLAGS.put(Material.BURNING_FURNACE, MODIFIED_ON_CLICK);
MATERIAL_FLAGS.put(Material.SIGN_POST, 0);
MATERIAL_FLAGS.put(Material.WOODEN_DOOR, MODIFIED_ON_CLICK);
MATERIAL_FLAGS.put(Material.LADDER, 0);
MATERIAL_FLAGS.put(Material.RAILS, 0);
MATERIAL_FLAGS.put(Material.COBBLESTONE_STAIRS, 0);
MATERIAL_FLAGS.put(Material.WALL_SIGN, 0);
MATERIAL_FLAGS.put(Material.LEVER, MODIFIED_ON_CLICK);
MATERIAL_FLAGS.put(Material.STONE_PLATE, 0);
MATERIAL_FLAGS.put(Material.IRON_DOOR_BLOCK, MODIFIED_ON_CLICK);
MATERIAL_FLAGS.put(Material.WOOD_PLATE, 0);
MATERIAL_FLAGS.put(Material.REDSTONE_ORE, 0);
MATERIAL_FLAGS.put(Material.GLOWING_REDSTONE_ORE, 0);
MATERIAL_FLAGS.put(Material.REDSTONE_TORCH_OFF, 0);
MATERIAL_FLAGS.put(Material.REDSTONE_TORCH_ON, 0);
MATERIAL_FLAGS.put(Material.STONE_BUTTON, MODIFIED_ON_CLICK);
MATERIAL_FLAGS.put(Material.SNOW, 0);
MATERIAL_FLAGS.put(Material.ICE, 0);
MATERIAL_FLAGS.put(Material.SNOW_BLOCK, 0);
MATERIAL_FLAGS.put(Material.CACTUS, 0);
MATERIAL_FLAGS.put(Material.CLAY, 0);
MATERIAL_FLAGS.put(Material.SUGAR_CANE_BLOCK, 0);
MATERIAL_FLAGS.put(Material.JUKEBOX, MODIFIED_ON_CLICK);
MATERIAL_FLAGS.put(Material.FENCE, 0);
MATERIAL_FLAGS.put(Material.PUMPKIN, 0);
MATERIAL_FLAGS.put(Material.NETHERRACK, 0);
MATERIAL_FLAGS.put(Material.SOUL_SAND, 0);
MATERIAL_FLAGS.put(Material.GLOWSTONE, 0);
MATERIAL_FLAGS.put(Material.PORTAL, 0);
MATERIAL_FLAGS.put(Material.JACK_O_LANTERN, 0);
MATERIAL_FLAGS.put(Material.CAKE_BLOCK, MODIFIED_ON_CLICK);
MATERIAL_FLAGS.put(Material.DIODE_BLOCK_OFF, MODIFIED_ON_CLICK);
MATERIAL_FLAGS.put(Material.DIODE_BLOCK_ON, MODIFIED_ON_CLICK);
MATERIAL_FLAGS.put(Material.STAINED_GLASS, 0);
MATERIAL_FLAGS.put(Material.TRAP_DOOR, MODIFIED_ON_CLICK);
MATERIAL_FLAGS.put(Material.MONSTER_EGGS, 0);
MATERIAL_FLAGS.put(Material.SMOOTH_BRICK, 0);
MATERIAL_FLAGS.put(Material.HUGE_MUSHROOM_1, 0);
MATERIAL_FLAGS.put(Material.HUGE_MUSHROOM_2, 0);
MATERIAL_FLAGS.put(Material.IRON_FENCE, 0);
MATERIAL_FLAGS.put(Material.THIN_GLASS, 0);
MATERIAL_FLAGS.put(Material.MELON_BLOCK, 0);
MATERIAL_FLAGS.put(Material.PUMPKIN_STEM, 0);
MATERIAL_FLAGS.put(Material.MELON_STEM, 0);
MATERIAL_FLAGS.put(Material.VINE, 0);
MATERIAL_FLAGS.put(Material.FENCE_GATE, MODIFIED_ON_CLICK);
MATERIAL_FLAGS.put(Material.BRICK_STAIRS, 0);
MATERIAL_FLAGS.put(Material.SMOOTH_STAIRS, 0);
MATERIAL_FLAGS.put(Material.MYCEL, 0);
MATERIAL_FLAGS.put(Material.WATER_LILY, 0);
MATERIAL_FLAGS.put(Material.NETHER_BRICK, 0);
MATERIAL_FLAGS.put(Material.NETHER_FENCE, 0);
MATERIAL_FLAGS.put(Material.NETHER_BRICK_STAIRS, 0);
MATERIAL_FLAGS.put(Material.NETHER_WARTS, 0);
MATERIAL_FLAGS.put(Material.ENCHANTMENT_TABLE, 0);
MATERIAL_FLAGS.put(Material.BREWING_STAND, MODIFIED_ON_CLICK);
MATERIAL_FLAGS.put(Material.CAULDRON, MODIFIED_ON_CLICK);
MATERIAL_FLAGS.put(Material.ENDER_PORTAL, 0);
MATERIAL_FLAGS.put(Material.ENDER_PORTAL_FRAME, 0);
MATERIAL_FLAGS.put(Material.ENDER_STONE, 0);
MATERIAL_FLAGS.put(Material.DRAGON_EGG, MODIFIED_ON_CLICK);
MATERIAL_FLAGS.put(Material.REDSTONE_LAMP_OFF, 0);
MATERIAL_FLAGS.put(Material.REDSTONE_LAMP_ON, 0);
MATERIAL_FLAGS.put(Material.WOOD_DOUBLE_STEP, 0);
MATERIAL_FLAGS.put(Material.WOOD_STEP, 0);
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.TRIPWIRE_HOOK, 0);
MATERIAL_FLAGS.put(Material.TRIPWIRE, 0);
MATERIAL_FLAGS.put(Material.EMERALD_BLOCK, 0);
MATERIAL_FLAGS.put(Material.SPRUCE_WOOD_STAIRS, 0);
MATERIAL_FLAGS.put(Material.BIRCH_WOOD_STAIRS, 0);
MATERIAL_FLAGS.put(Material.JUNGLE_WOOD_STAIRS, 0);
MATERIAL_FLAGS.put(Material.COMMAND, MODIFIED_ON_CLICK);
MATERIAL_FLAGS.put(Material.BEACON, MODIFIED_ON_CLICK);
MATERIAL_FLAGS.put(Material.COBBLE_WALL, 0);
MATERIAL_FLAGS.put(Material.FLOWER_POT, MODIFIED_ON_CLICK);
MATERIAL_FLAGS.put(Material.CARROT, 0);
MATERIAL_FLAGS.put(Material.POTATO, 0);
MATERIAL_FLAGS.put(Material.WOOD_BUTTON, MODIFIED_ON_CLICK);
MATERIAL_FLAGS.put(Material.SKULL, 0);
MATERIAL_FLAGS.put(Material.ANVIL, MODIFIED_ON_CLICK);
MATERIAL_FLAGS.put(Material.TRAPPED_CHEST, MODIFIED_ON_CLICK);
MATERIAL_FLAGS.put(Material.GOLD_PLATE, 0);
MATERIAL_FLAGS.put(Material.IRON_PLATE, 0);
MATERIAL_FLAGS.put(Material.REDSTONE_COMPARATOR_OFF, MODIFIED_ON_CLICK);
MATERIAL_FLAGS.put(Material.REDSTONE_COMPARATOR_ON, MODIFIED_ON_CLICK);
MATERIAL_FLAGS.put(Material.DAYLIGHT_DETECTOR, MODIFIED_ON_CLICK);
MATERIAL_FLAGS.put(Material.REDSTONE_BLOCK, 0);
MATERIAL_FLAGS.put(Material.QUARTZ_ORE, 0);
MATERIAL_FLAGS.put(Material.HOPPER, MODIFIED_ON_CLICK);
MATERIAL_FLAGS.put(Material.QUARTZ_BLOCK, 0);
MATERIAL_FLAGS.put(Material.QUARTZ_STAIRS, 0);
MATERIAL_FLAGS.put(Material.ACTIVATOR_RAIL, 0);
MATERIAL_FLAGS.put(Material.DROPPER, MODIFIED_ON_CLICK);
MATERIAL_FLAGS.put(Material.STAINED_CLAY, 0);
MATERIAL_FLAGS.put(Material.STAINED_GLASS_PANE, 0);
MATERIAL_FLAGS.put(Material.LEAVES_2, 0);
MATERIAL_FLAGS.put(Material.LOG_2, 0);
MATERIAL_FLAGS.put(Material.ACACIA_STAIRS, 0);
MATERIAL_FLAGS.put(Material.DARK_OAK_STAIRS, 0);
MATERIAL_FLAGS.put(Material.HAY_BLOCK, 0);
MATERIAL_FLAGS.put(Material.CARPET, 0);
MATERIAL_FLAGS.put(Material.HARD_CLAY, 0);
MATERIAL_FLAGS.put(Material.COAL_BLOCK, 0);
MATERIAL_FLAGS.put(Material.PACKED_ICE, 0);
MATERIAL_FLAGS.put(Material.DOUBLE_PLANT, 0);
MATERIAL_FLAGS.put(Material.IRON_SPADE, 0);
MATERIAL_FLAGS.put(Material.IRON_PICKAXE, 0);
MATERIAL_FLAGS.put(Material.IRON_AXE, 0);
MATERIAL_FLAGS.put(Material.FLINT_AND_STEEL, 0);
MATERIAL_FLAGS.put(Material.APPLE, 0);
MATERIAL_FLAGS.put(Material.BOW, 0);
MATERIAL_FLAGS.put(Material.ARROW, 0);
MATERIAL_FLAGS.put(Material.COAL, 0);
MATERIAL_FLAGS.put(Material.DIAMOND, 0);
MATERIAL_FLAGS.put(Material.IRON_INGOT, 0);
MATERIAL_FLAGS.put(Material.GOLD_INGOT, 0);
MATERIAL_FLAGS.put(Material.IRON_SWORD, 0);
MATERIAL_FLAGS.put(Material.WOOD_SWORD, 0);
MATERIAL_FLAGS.put(Material.WOOD_SPADE, 0);
MATERIAL_FLAGS.put(Material.WOOD_PICKAXE, 0);
MATERIAL_FLAGS.put(Material.WOOD_AXE, 0);
MATERIAL_FLAGS.put(Material.STONE_SWORD, 0);
MATERIAL_FLAGS.put(Material.STONE_SPADE, 0);
MATERIAL_FLAGS.put(Material.STONE_PICKAXE, 0);
MATERIAL_FLAGS.put(Material.STONE_AXE, 0);
MATERIAL_FLAGS.put(Material.DIAMOND_SWORD, 0);
MATERIAL_FLAGS.put(Material.DIAMOND_SPADE, 0);
MATERIAL_FLAGS.put(Material.DIAMOND_PICKAXE, 0);
MATERIAL_FLAGS.put(Material.DIAMOND_AXE, 0);
MATERIAL_FLAGS.put(Material.STICK, 0);
MATERIAL_FLAGS.put(Material.BOWL, 0);
MATERIAL_FLAGS.put(Material.MUSHROOM_SOUP, 0);
MATERIAL_FLAGS.put(Material.GOLD_SWORD, 0);
MATERIAL_FLAGS.put(Material.GOLD_SPADE, 0);
MATERIAL_FLAGS.put(Material.GOLD_PICKAXE, 0);
MATERIAL_FLAGS.put(Material.GOLD_AXE, 0);
MATERIAL_FLAGS.put(Material.STRING, 0);
MATERIAL_FLAGS.put(Material.FEATHER, 0);
MATERIAL_FLAGS.put(Material.SULPHUR, 0);
MATERIAL_FLAGS.put(Material.WOOD_HOE, MODIFIES_BLOCKS);
MATERIAL_FLAGS.put(Material.STONE_HOE, MODIFIES_BLOCKS);
MATERIAL_FLAGS.put(Material.IRON_HOE, MODIFIES_BLOCKS);
MATERIAL_FLAGS.put(Material.DIAMOND_HOE, MODIFIES_BLOCKS);
MATERIAL_FLAGS.put(Material.GOLD_HOE, MODIFIES_BLOCKS);
MATERIAL_FLAGS.put(Material.SEEDS, MODIFIES_BLOCKS);
MATERIAL_FLAGS.put(Material.WHEAT, 0);
MATERIAL_FLAGS.put(Material.BREAD, 0);
MATERIAL_FLAGS.put(Material.LEATHER_HELMET, 0);
MATERIAL_FLAGS.put(Material.LEATHER_CHESTPLATE, 0);
MATERIAL_FLAGS.put(Material.LEATHER_LEGGINGS, 0);
MATERIAL_FLAGS.put(Material.LEATHER_BOOTS, 0);
MATERIAL_FLAGS.put(Material.CHAINMAIL_HELMET, 0);
MATERIAL_FLAGS.put(Material.CHAINMAIL_CHESTPLATE, 0);
MATERIAL_FLAGS.put(Material.CHAINMAIL_LEGGINGS, 0);
MATERIAL_FLAGS.put(Material.CHAINMAIL_BOOTS, 0);
MATERIAL_FLAGS.put(Material.IRON_HELMET, 0);
MATERIAL_FLAGS.put(Material.IRON_CHESTPLATE, 0);
MATERIAL_FLAGS.put(Material.IRON_LEGGINGS, 0);
MATERIAL_FLAGS.put(Material.IRON_BOOTS, 0);
MATERIAL_FLAGS.put(Material.DIAMOND_HELMET, 0);
MATERIAL_FLAGS.put(Material.DIAMOND_CHESTPLATE, 0);
MATERIAL_FLAGS.put(Material.DIAMOND_LEGGINGS, 0);
MATERIAL_FLAGS.put(Material.DIAMOND_BOOTS, 0);
MATERIAL_FLAGS.put(Material.GOLD_HELMET, 0);
MATERIAL_FLAGS.put(Material.GOLD_CHESTPLATE, 0);
MATERIAL_FLAGS.put(Material.GOLD_LEGGINGS, 0);
MATERIAL_FLAGS.put(Material.GOLD_BOOTS, 0);
MATERIAL_FLAGS.put(Material.FLINT, 0);
MATERIAL_FLAGS.put(Material.PORK, 0);
MATERIAL_FLAGS.put(Material.GRILLED_PORK, 0);
MATERIAL_FLAGS.put(Material.PAINTING, 0);
MATERIAL_FLAGS.put(Material.GOLDEN_APPLE, 0);
MATERIAL_FLAGS.put(Material.SIGN, 0);
MATERIAL_FLAGS.put(Material.WOOD_DOOR, 0);
MATERIAL_FLAGS.put(Material.BUCKET, 0);
MATERIAL_FLAGS.put(Material.WATER_BUCKET, 0);
MATERIAL_FLAGS.put(Material.LAVA_BUCKET, 0);
MATERIAL_FLAGS.put(Material.MINECART, 0);
MATERIAL_FLAGS.put(Material.SADDLE, 0);
MATERIAL_FLAGS.put(Material.IRON_DOOR, 0);
MATERIAL_FLAGS.put(Material.REDSTONE, 0);
MATERIAL_FLAGS.put(Material.SNOW_BALL, 0);
MATERIAL_FLAGS.put(Material.BOAT, 0);
MATERIAL_FLAGS.put(Material.LEATHER, 0);
MATERIAL_FLAGS.put(Material.MILK_BUCKET, 0);
MATERIAL_FLAGS.put(Material.CLAY_BRICK, 0);
MATERIAL_FLAGS.put(Material.CLAY_BALL, 0);
MATERIAL_FLAGS.put(Material.SUGAR_CANE, 0);
MATERIAL_FLAGS.put(Material.PAPER, 0);
MATERIAL_FLAGS.put(Material.BOOK, 0);
MATERIAL_FLAGS.put(Material.SLIME_BALL, 0);
MATERIAL_FLAGS.put(Material.STORAGE_MINECART, 0);
MATERIAL_FLAGS.put(Material.POWERED_MINECART, 0);
MATERIAL_FLAGS.put(Material.EGG, 0);
MATERIAL_FLAGS.put(Material.COMPASS, 0);
MATERIAL_FLAGS.put(Material.FISHING_ROD, 0);
MATERIAL_FLAGS.put(Material.WATCH, 0);
MATERIAL_FLAGS.put(Material.GLOWSTONE_DUST, 0);
MATERIAL_FLAGS.put(Material.RAW_FISH, 0);
MATERIAL_FLAGS.put(Material.COOKED_FISH, 0);
MATERIAL_FLAGS.put(Material.INK_SACK, 0);
MATERIAL_FLAGS.put(Material.BONE, 0);
MATERIAL_FLAGS.put(Material.SUGAR, 0);
MATERIAL_FLAGS.put(Material.CAKE, 0);
MATERIAL_FLAGS.put(Material.BED, 0);
MATERIAL_FLAGS.put(Material.DIODE, 0);
MATERIAL_FLAGS.put(Material.COOKIE, 0);
MATERIAL_FLAGS.put(Material.MAP, 0);
MATERIAL_FLAGS.put(Material.SHEARS, MODIFIES_BLOCKS);
MATERIAL_FLAGS.put(Material.MELON, 0);
MATERIAL_FLAGS.put(Material.PUMPKIN_SEEDS, 0);
MATERIAL_FLAGS.put(Material.MELON_SEEDS, 0);
MATERIAL_FLAGS.put(Material.RAW_BEEF, 0);
MATERIAL_FLAGS.put(Material.COOKED_BEEF, 0);
MATERIAL_FLAGS.put(Material.RAW_CHICKEN, 0);
MATERIAL_FLAGS.put(Material.COOKED_CHICKEN, 0);
MATERIAL_FLAGS.put(Material.ROTTEN_FLESH, 0);
MATERIAL_FLAGS.put(Material.ENDER_PEARL, 0);
MATERIAL_FLAGS.put(Material.BLAZE_ROD, 0);
MATERIAL_FLAGS.put(Material.GHAST_TEAR, 0);
MATERIAL_FLAGS.put(Material.GOLD_NUGGET, 0);
MATERIAL_FLAGS.put(Material.NETHER_STALK, 0);
MATERIAL_FLAGS.put(Material.POTION, 0);
MATERIAL_FLAGS.put(Material.GLASS_BOTTLE, 0);
MATERIAL_FLAGS.put(Material.SPIDER_EYE, 0);
MATERIAL_FLAGS.put(Material.FERMENTED_SPIDER_EYE, 0);
MATERIAL_FLAGS.put(Material.BLAZE_POWDER, 0);
MATERIAL_FLAGS.put(Material.MAGMA_CREAM, 0);
MATERIAL_FLAGS.put(Material.BREWING_STAND_ITEM, 0);
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.EXP_BOTTLE, 0);
MATERIAL_FLAGS.put(Material.FIREBALL, 0);
MATERIAL_FLAGS.put(Material.BOOK_AND_QUILL, 0);
MATERIAL_FLAGS.put(Material.WRITTEN_BOOK, 0);
MATERIAL_FLAGS.put(Material.EMERALD, 0);
MATERIAL_FLAGS.put(Material.ITEM_FRAME, 0);
MATERIAL_FLAGS.put(Material.FLOWER_POT_ITEM, 0);
MATERIAL_FLAGS.put(Material.CARROT_ITEM, 0);
MATERIAL_FLAGS.put(Material.POTATO_ITEM, 0);
MATERIAL_FLAGS.put(Material.BAKED_POTATO, 0);
MATERIAL_FLAGS.put(Material.POISONOUS_POTATO, 0);
MATERIAL_FLAGS.put(Material.EMPTY_MAP, 0);
MATERIAL_FLAGS.put(Material.GOLDEN_CARROT, 0);
MATERIAL_FLAGS.put(Material.SKULL_ITEM, 0);
MATERIAL_FLAGS.put(Material.CARROT_STICK, 0);
MATERIAL_FLAGS.put(Material.NETHER_STAR, 0);
MATERIAL_FLAGS.put(Material.PUMPKIN_PIE, 0);
MATERIAL_FLAGS.put(Material.FIREWORK, 0);
MATERIAL_FLAGS.put(Material.FIREWORK_CHARGE, 0);
MATERIAL_FLAGS.put(Material.ENCHANTED_BOOK, 0);
MATERIAL_FLAGS.put(Material.REDSTONE_COMPARATOR, 0);
MATERIAL_FLAGS.put(Material.NETHER_BRICK_ITEM, 0);
MATERIAL_FLAGS.put(Material.QUARTZ, 0);
MATERIAL_FLAGS.put(Material.EXPLOSIVE_MINECART, 0);
MATERIAL_FLAGS.put(Material.HOPPER_MINECART, 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.LEASH, 0);
MATERIAL_FLAGS.put(Material.NAME_TAG, 0);
MATERIAL_FLAGS.put(Material.COMMAND_MINECART, 0);
MATERIAL_FLAGS.put(Material.GOLD_RECORD, 0);
MATERIAL_FLAGS.put(Material.GREEN_RECORD, 0);
MATERIAL_FLAGS.put(Material.RECORD_3, 0);
MATERIAL_FLAGS.put(Material.RECORD_4, 0);
MATERIAL_FLAGS.put(Material.RECORD_5, 0);
MATERIAL_FLAGS.put(Material.RECORD_6, 0);
MATERIAL_FLAGS.put(Material.RECORD_7, 0);
MATERIAL_FLAGS.put(Material.RECORD_8, 0);
MATERIAL_FLAGS.put(Material.RECORD_9, 0);
MATERIAL_FLAGS.put(Material.RECORD_10, 0);
MATERIAL_FLAGS.put(Material.RECORD_11, 0);
MATERIAL_FLAGS.put(Material.RECORD_12, 0);
}
private Materials() {
}
/**
* Get the related material for an entity type.
*
* @param type the entity type
* @return the related material or {@code null} if one is not known or exists
*/
@Nullable
public static Material getRelatedMaterial(EntityType type) {
return ENTITY_ITEMS.get(type);
}
/**
* Get the material of the block placed by the given bucket, defaulting
* to water if the bucket type is not known.
*
* <p>If a non-bucket material is given, it will be assumed to be
* an unknown bucket type. If the given bucket doesn't have a block form
* (it can't be placed), then water will be returned (i.e. for milk).
* Be aware that either the stationary or non-stationary material may be
* returned.</p>
*
* @param type the bucket material
* @return the block material
*/
public static Material getBucketBlockMaterial(Material type) {
switch (type) {
case LAVA_BUCKET:
return Material.LAVA;
case MILK_BUCKET:
return Material.WATER;
default:
return Material.WATER;
}
}
/**
* Test whether the given material is a mushroom.
*
* @param material the material
* @return true if a mushroom block
*/
public static boolean isMushroom(Material material) {
return material == Material.RED_MUSHROOM || material == Material.BROWN_MUSHROOM;
}
/**
* Test whether the given material is a leaf block.
*
* @param material the material
* @return true if a leaf block
*/
public static boolean isLeaf(Material material) {
return material == Material.LEAVES || material == Material.LEAVES_2;
}
/**
* Test whether the given material is a liquid block.
*
* @param material the material
* @return true if a liquid block
*/
public static boolean isLiquid(Material material) {
return isWater(material) || isLava(material);
}
/**
* Test whether the given material is water.
*
* @param material the material
* @return true if a water block
*/
public static boolean isWater(Material material) {
return material == Material.WATER || material == Material.STATIONARY_WATER;
}
/**
* Test whether the given material is lava.
*
* @param material the material
* @return true if a lava block
*/
public static boolean isLava(Material material) {
return material == Material.LAVA || material == Material.STATIONARY_LAVA;
}
/**
* Test whether the given material is a portal material.
*
* @param material the material
* @return true if a portal block
*/
public static boolean isPortal(Material material) {
return material == Material.PORTAL || material == Material.ENDER_PORTAL;
}
/**
* Test whether the given material data is of the given dye color.
*
* <p>Returns false for non-dyed items.</p>
*
* @param data the data
* @return true if it is the provided dye color
*/
public static boolean isDyeColor(MaterialData data, DyeColor color) {
return data instanceof Dye && ((Dye) data).getColor() == color;
}
/**
* Test whether the given material is a rail block.
*
* @param material the material
* @return true if a rail block
*/
public static boolean isRailBlock(Material material) {
return material == Material.RAILS
|| material == Material.ACTIVATOR_RAIL
|| material == Material.DETECTOR_RAIL
|| material == Material.POWERED_RAIL;
}
/**
* Test whether the given material is a piston block, not including
* the "technical blocks" such as the piston extension block.
*
* @param material the material
* @return true if a piston block
*/
public static boolean isPistonBlock(Material material) {
return material == Material.PISTON_BASE
|| material == Material.PISTON_STICKY_BASE;
}
/**
* Test whether the given material is a Minecart.
*
* @param material the material
* @return true if a Minecart item
*/
public static boolean isMinecart(Material material) {
return material == Material.MINECART
|| material == Material.COMMAND_MINECART
|| material == Material.EXPLOSIVE_MINECART
|| material == Material.HOPPER_MINECART
|| material == Material.POWERED_MINECART
|| material == Material.STORAGE_MINECART;
}
/**
* Test whether the given material is an inventory block.
*
* @param material the material
* @return true if an inventory block
*/
public static boolean isInventoryBlock(Material material) {
return material == Material.CHEST
|| material == Material.JUKEBOX
|| material == Material.DISPENSER
|| material == Material.FURNACE
|| material == Material.BURNING_FURNACE
|| material == Material.BREWING_STAND
|| material == Material.TRAPPED_CHEST
|| material == Material.HOPPER
|| material == Material.DROPPER;
}
/**
* Test whether the given material is a block that is modified when it is
* left or right clicked.
*
* <p>This test is conservative, returning true for blocks that it is not
* aware of.</p>
*
* @param material the material
* @return true if the block is modified
*/
public static boolean isBlockModifiedOnClick(Material material) {
Integer flags = MATERIAL_FLAGS.get(material);
return flags == null || (flags & MODIFIED_ON_CLICK) == MODIFIED_ON_CLICK;
}
/**
* Test whether the given item modifies a given block when right clicked.
*
* <p>This test is conservative, returning true for items that it is not
* aware of or does not have the details for.</p>
*
* @param item the item
* @param block the block
* @return true if the item is applied to the block
*/
public static boolean isItemAppliedToBlock(Material item, Material block) {
Integer flags = MATERIAL_FLAGS.get(item);
return flags == null || (flags & MODIFIES_BLOCKS) == MODIFIES_BLOCKS;
}
}

View File

@ -1,86 +1,88 @@
/*
* WorldGuard, a suite of tools for Minecraft
* Copyright (C) sk89q <http://www.sk89q.com>
* Copyright (C) WorldGuard team and contributors
*
* This program is free software: you can redistribute it and/or modify it
* under the terms of the GNU Lesser General Public License as published by the
* Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License
* for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package com.sk89q.worldguard.bukkit;
import 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;
}
}
}
/*
* WorldGuard, a suite of tools for Minecraft
* Copyright (C) sk89q <http://www.sk89q.com>
* Copyright (C) WorldGuard team and contributors
*
* This program is free software: you can redistribute it and/or modify it
* under the terms of the GNU Lesser General Public License as published by the
* Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License
* for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package com.sk89q.worldguard.bukkit.util;
import com.sk89q.worldguard.bukkit.WorldGuardPlugin;
import com.sk89q.worldguard.bukkit.listener.FlagStateManager;
import org.bukkit.Location;
import org.bukkit.World;
import org.bukkit.entity.Player;
import com.sk89q.worldedit.Vector;
import com.sk89q.worldguard.protection.ApplicableRegionSet;
import com.sk89q.worldguard.protection.flags.DefaultFlag;
import com.sk89q.worldguard.protection.flags.StateFlag;
import com.sk89q.worldguard.protection.managers.RegionManager;
public final class RegionQueryUtil {
private RegionQueryUtil() {
}
public static boolean isInvincible(WorldGuardPlugin plugin, Player player) {
return isInvincible(plugin, player, null);
}
public static boolean isInvincible(WorldGuardPlugin plugin, Player player,
ApplicableRegionSet set) {
Location loc = player.getLocation();
World world = player.getWorld();
FlagStateManager.PlayerFlagState state = plugin.getFlagStateManager().getState(player);
if (state.lastInvincibleWorld == null ||
!state.lastInvincibleWorld.equals(world) ||
state.lastInvincibleX != loc.getBlockX() ||
state.lastInvincibleY != loc.getBlockY() ||
state.lastInvincibleZ != loc.getBlockZ()) {
state.lastInvincibleX = loc.getBlockX();
state.lastInvincibleY = loc.getBlockY();
state.lastInvincibleZ = loc.getBlockZ();
state.lastInvincibleWorld = world;
if (set == null) {
Vector vec = new Vector(state.lastInvincibleX,
state.lastInvincibleY, state.lastInvincibleZ);
RegionManager mgr = plugin.getGlobalRegionManager().get(world);
set = mgr.getApplicableRegions(vec);
}
state.wasInvincible = set.allows(DefaultFlag.INVINCIBILITY, plugin.wrapPlayer(player));
}
return state.wasInvincible;
}
public static Boolean isAllowedInvinciblity(WorldGuardPlugin plugin, Player player) {
World world = player.getWorld();
FlagStateManager.PlayerFlagState state = plugin.getFlagStateManager().getState(player);
Vector vec = new Vector(state.lastInvincibleX, state.lastInvincibleY, state.lastInvincibleZ);
StateFlag.State regionState = plugin.getGlobalRegionManager().get(world).
getApplicableRegions(vec).getFlag(DefaultFlag.INVINCIBILITY, plugin.wrapPlayer(player));
if (regionState == StateFlag.State.ALLOW) {
return Boolean.TRUE;
} else if (regionState == StateFlag.State.DENY) {
return Boolean.FALSE;
} else {
return null;
}
}
}

View File

@ -1,343 +1,346 @@
/*
* WorldGuard, a suite of tools for Minecraft
* Copyright (C) sk89q <http://www.sk89q.com>
* Copyright (C) WorldGuard team and contributors
*
* This program is free software: you can redistribute it and/or modify it
* under the terms of the GNU Lesser General Public License as published by the
* Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License
* for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package com.sk89q.worldguard.bukkit;
import java.io.BufferedWriter;
import java.io.File;
import java.io.FileWriter;
import java.io.IOException;
import java.lang.reflect.Field;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import org.bukkit.Server;
import org.bukkit.World;
import org.bukkit.entity.Entity;
import org.bukkit.plugin.Plugin;
import com.sk89q.worldguard.protection.GlobalRegionManager;
import com.sk89q.worldguard.protection.flags.DefaultFlag;
import com.sk89q.worldguard.protection.flags.Flag;
import com.sk89q.worldguard.protection.flags.StateFlag;
import com.sk89q.worldguard.protection.managers.RegionManager;
import com.sk89q.worldguard.protection.regions.ProtectedRegion;
import com.sk89q.worldguard.util.LogListBlock;
public class ReportWriter {
private static final SimpleDateFormat dateFmt =
new SimpleDateFormat("yyyy-MM-dd kk:mm Z");
private Date date = new Date();
private StringBuilder output = new StringBuilder();
public ReportWriter(WorldGuardPlugin plugin) {
appendReportHeader(plugin);
appendServerInformation(plugin.getServer());
appendPluginInformation(plugin.getServer().getPluginManager().getPlugins());
appendWorldInformation(plugin.getServer().getWorlds());
appendGlobalConfiguration(plugin.getGlobalStateManager());
appendWorldConfigurations(plugin, plugin.getServer().getWorlds(),
plugin.getGlobalRegionManager(), plugin.getGlobalStateManager());
appendln("-------------");
appendln("END OF REPORT");
appendln();
}
protected static String repeat(String str, int n) {
if(str == null) {
return null;
}
StringBuilder sb = new StringBuilder();
for (int i = 0; i < n; i++) {
sb.append(str);
}
return sb.toString();
}
protected void appendln(String text) {
output.append(text);
output.append("\r\n");
}
protected void appendln(String text, Object ... args) {
output.append(String.format(text, args));
output.append("\r\n");
}
protected void append(LogListBlock log) {
output.append(log.toString());
}
protected void appendln() {
output.append("\r\n");
}
protected void appendHeader(String text) {
String rule = repeat("-", text.length());
output.append(rule);
output.append("\r\n");
appendln(text);
output.append(rule);
output.append("\r\n");
appendln();
}
private void appendReportHeader(WorldGuardPlugin plugin) {
appendln("WorldGuard Configuration Report");
appendln("Generated " + dateFmt.format(date));
appendln();
appendln("Version: " + plugin.getDescription().getVersion());
appendln();
}
private void appendGlobalConfiguration(ConfigurationManager config) {
appendHeader("Global Configuration");
LogListBlock log = new LogListBlock();
LogListBlock configLog = log.putChild("Configuration");
Class<? extends ConfigurationManager> cls = config.getClass();
for (Field field : cls.getFields()) {
try {
String name = field.getName();
// store these elsewhere maybe?
if (name.equals("CONFIG_HEADER")
|| name.equals("hostKeys")
|| name.equals("sqlPassword")) {
continue;
}
Object val = field.get(config);
configLog.put(name, val);
} catch (IllegalArgumentException e) {
e.printStackTrace();
} catch (IllegalAccessException ignore) {
}
}
append(log);
appendln();
}
private void appendServerInformation(Server server) {
appendHeader("Server Information");
LogListBlock log = new LogListBlock();
Runtime runtime = Runtime.getRuntime();
log.put("Java", "%s %s (%s)",
System.getProperty("java.vendor"),
System.getProperty("java.version"),
System.getProperty("java.vendor.url"));
log.put("Operating system", "%s %s (%s)",
System.getProperty("os.name"),
System.getProperty("os.version"),
System.getProperty("os.arch"));
log.put("Available processors", runtime.availableProcessors());
log.put("Free memory", runtime.freeMemory() / 1024 / 1024 + " MB");
log.put("Max memory", runtime.maxMemory() / 1024 / 1024 + " MB");
log.put("Total memory", runtime.totalMemory() / 1024 / 1024 + " MB");
log.put("Server ID", server.getServerId());
log.put("Server name", server.getServerName());
log.put("Implementation", server.getVersion());
//log.put("Address", server.getIp(), server.getPort());
log.put("Player count", "%d/%d",
server.getOnlinePlayers().length, server.getMaxPlayers());
append(log);
appendln();
}
private void appendPluginInformation(Plugin[] plugins) {
appendHeader("Plugins (" + plugins.length + ")");
LogListBlock log = new LogListBlock();
for (Plugin plugin : plugins) {
log.put(plugin.getDescription().getName(), plugin.getDescription().getVersion());
}
append(log);
appendln();
/*appendHeader("Plugin Information");
log = new LogListBlock();
for (Plugin plugin : plugins) {
log.putChild(plugin.getDescription().getName())
.put("Data folder", plugin.getDataFolder())
.put("Website", plugin.getDescription().getWebsite())
.put("Entry point", plugin.getDescription().getMain());
}
append(log);
appendln();*/
}
private void appendWorldInformation(List<World> worlds) {
appendHeader("Worlds");
LogListBlock log = new LogListBlock();
int i = 0;
for (World world : worlds) {
int loadedChunkCount = world.getLoadedChunks().length;
LogListBlock worldLog = log.putChild(world.getName() + " (" + i + ")");
LogListBlock infoLog = worldLog.putChild("Information");
LogListBlock entitiesLog = worldLog.putChild("Entities");
infoLog.put("Seed", world.getSeed());
infoLog.put("Environment", world.getEnvironment().toString());
infoLog.put("Player count", world.getPlayers().size());
infoLog.put("Entity count", world.getEntities().size());
infoLog.put("Loaded chunk count", loadedChunkCount);
infoLog.put("Spawn location", world.getSpawnLocation());
infoLog.put("Raw time", world.getFullTime());
Map<Class<? extends Entity>, Integer> entityCounts =
new HashMap<Class<? extends Entity>, Integer>();
// Collect entities
for (Entity entity : world.getEntities()) {
Class<? extends Entity> cls = entity.getClass();
if (entityCounts.containsKey(cls)) {
entityCounts.put(cls, entityCounts.get(cls) + 1);
} else {
entityCounts.put(cls, 1);
}
}
// Print entities
for (Map.Entry<Class<? extends Entity>, Integer> entry
: entityCounts.entrySet()) {
entitiesLog.put(entry.getKey().getSimpleName(),
"%d [%f/chunk]",
entry.getValue(),
(float) (entry.getValue() / (double) loadedChunkCount));
}
i++;
}
append(log);
appendln();
}
private void appendWorldConfigurations(WorldGuardPlugin plugin, List<World> worlds,
GlobalRegionManager regionMgr, ConfigurationManager mgr) {
appendHeader("World Configurations");
LogListBlock log = new LogListBlock();
int i = 0;
for (World world : worlds) {
LogListBlock worldLog = log.putChild(world.getName() + " (" + i + ")");
LogListBlock infoLog = worldLog.putChild("Information");
LogListBlock configLog = worldLog.putChild("Configuration");
LogListBlock blacklistLog = worldLog.putChild("Blacklist");
LogListBlock regionsLog = worldLog.putChild("Region manager");
infoLog.put("Configuration file", (new File(plugin.getDataFolder(), "worlds/"
+ world.getName() + "/config.yml")).getAbsoluteFile());
infoLog.put("Blacklist file", (new File(plugin.getDataFolder(), "worlds/"
+ world.getName() + "/blacklist.txt")).getAbsoluteFile());
infoLog.put("Regions file", (new File(plugin.getDataFolder(), "worlds/"
+ world.getName() + "/regions.yml")).getAbsoluteFile());
WorldConfiguration config = mgr.get(world);
Class<? extends WorldConfiguration> cls = config.getClass();
for (Field field : cls.getFields()) {
try {
Object val = field.get(config);
configLog.put(field.getName(), String.valueOf(val));
} catch (IllegalArgumentException e) {
e.printStackTrace();
} catch (IllegalAccessException ignore) {
}
}
if (config.getBlacklist() == null) {
blacklistLog.put("State", "DISABLED");
} else {
blacklistLog.put("State", "Enabled");
blacklistLog.put("Number of items",
config.getBlacklist().getItemCount());
blacklistLog.put("Is whitelist",
config.getBlacklist().isWhitelist());
}
RegionManager worldRegions = regionMgr.get(world);
regionsLog.put("Type", worldRegions.getClass().getCanonicalName());
regionsLog.put("Number of regions", worldRegions.getRegions().size());
LogListBlock globalRegionLog = regionsLog.putChild("Global region");
ProtectedRegion globalRegion = worldRegions.getRegion("__global__");
if (globalRegion == null) {
globalRegionLog.put("Status", "UNDEFINED");
} else {
for (Flag<?> flag : DefaultFlag.getFlags()) {
if (flag instanceof StateFlag) {
globalRegionLog.put(flag.getName(),
globalRegion.getFlag(flag));
}
}
}
}
append(log);
appendln();
}
public void write(File file) throws IOException {
FileWriter writer = null;
BufferedWriter out;
try {
writer = new FileWriter(file);
out = new BufferedWriter(writer);
out.write(output.toString());
out.close();
} finally {
if (writer != null) {
try {
writer.close();
} catch (IOException ignore) {
}
}
}
}
@Override
public String toString() {
return output.toString();
}
}
/*
* WorldGuard, a suite of tools for Minecraft
* Copyright (C) sk89q <http://www.sk89q.com>
* Copyright (C) WorldGuard team and contributors
*
* This program is free software: you can redistribute it and/or modify it
* under the terms of the GNU Lesser General Public License as published by the
* Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License
* for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package com.sk89q.worldguard.bukkit.util;
import java.io.BufferedWriter;
import java.io.File;
import java.io.FileWriter;
import java.io.IOException;
import java.lang.reflect.Field;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import com.sk89q.worldguard.bukkit.ConfigurationManager;
import com.sk89q.worldguard.bukkit.WorldConfiguration;
import com.sk89q.worldguard.bukkit.WorldGuardPlugin;
import org.bukkit.Server;
import org.bukkit.World;
import org.bukkit.entity.Entity;
import org.bukkit.plugin.Plugin;
import com.sk89q.worldguard.protection.GlobalRegionManager;
import com.sk89q.worldguard.protection.flags.DefaultFlag;
import com.sk89q.worldguard.protection.flags.Flag;
import com.sk89q.worldguard.protection.flags.StateFlag;
import com.sk89q.worldguard.protection.managers.RegionManager;
import com.sk89q.worldguard.protection.regions.ProtectedRegion;
import com.sk89q.worldguard.util.LogListBlock;
public class ReportWriter {
private static final SimpleDateFormat dateFmt =
new SimpleDateFormat("yyyy-MM-dd kk:mm Z");
private Date date = new Date();
private StringBuilder output = new StringBuilder();
public ReportWriter(WorldGuardPlugin plugin) {
appendReportHeader(plugin);
appendServerInformation(plugin.getServer());
appendPluginInformation(plugin.getServer().getPluginManager().getPlugins());
appendWorldInformation(plugin.getServer().getWorlds());
appendGlobalConfiguration(plugin.getGlobalStateManager());
appendWorldConfigurations(plugin, plugin.getServer().getWorlds(),
plugin.getGlobalRegionManager(), plugin.getGlobalStateManager());
appendln("-------------");
appendln("END OF REPORT");
appendln();
}
protected static String repeat(String str, int n) {
if(str == null) {
return null;
}
StringBuilder sb = new StringBuilder();
for (int i = 0; i < n; i++) {
sb.append(str);
}
return sb.toString();
}
protected void appendln(String text) {
output.append(text);
output.append("\r\n");
}
protected void appendln(String text, Object ... args) {
output.append(String.format(text, args));
output.append("\r\n");
}
protected void append(LogListBlock log) {
output.append(log.toString());
}
protected void appendln() {
output.append("\r\n");
}
protected void appendHeader(String text) {
String rule = repeat("-", text.length());
output.append(rule);
output.append("\r\n");
appendln(text);
output.append(rule);
output.append("\r\n");
appendln();
}
private void appendReportHeader(WorldGuardPlugin plugin) {
appendln("WorldGuard Configuration Report");
appendln("Generated " + dateFmt.format(date));
appendln();
appendln("Version: " + plugin.getDescription().getVersion());
appendln();
}
private void appendGlobalConfiguration(ConfigurationManager config) {
appendHeader("Global Configuration");
LogListBlock log = new LogListBlock();
LogListBlock configLog = log.putChild("Configuration");
Class<? extends ConfigurationManager> cls = config.getClass();
for (Field field : cls.getFields()) {
try {
String name = field.getName();
// store these elsewhere maybe?
if (name.equals("CONFIG_HEADER")
|| name.equals("hostKeys")
|| name.equals("sqlPassword")) {
continue;
}
Object val = field.get(config);
configLog.put(name, val);
} catch (IllegalArgumentException e) {
e.printStackTrace();
} catch (IllegalAccessException ignore) {
}
}
append(log);
appendln();
}
private void appendServerInformation(Server server) {
appendHeader("Server Information");
LogListBlock log = new LogListBlock();
Runtime runtime = Runtime.getRuntime();
log.put("Java", "%s %s (%s)",
System.getProperty("java.vendor"),
System.getProperty("java.version"),
System.getProperty("java.vendor.url"));
log.put("Operating system", "%s %s (%s)",
System.getProperty("os.name"),
System.getProperty("os.version"),
System.getProperty("os.arch"));
log.put("Available processors", runtime.availableProcessors());
log.put("Free memory", runtime.freeMemory() / 1024 / 1024 + " MB");
log.put("Max memory", runtime.maxMemory() / 1024 / 1024 + " MB");
log.put("Total memory", runtime.totalMemory() / 1024 / 1024 + " MB");
log.put("Server ID", server.getServerId());
log.put("Server name", server.getServerName());
log.put("Implementation", server.getVersion());
//log.put("Address", server.getIp(), server.getPort());
log.put("Player count", "%d/%d",
server.getOnlinePlayers().length, server.getMaxPlayers());
append(log);
appendln();
}
private void appendPluginInformation(Plugin[] plugins) {
appendHeader("Plugins (" + plugins.length + ")");
LogListBlock log = new LogListBlock();
for (Plugin plugin : plugins) {
log.put(plugin.getDescription().getName(), plugin.getDescription().getVersion());
}
append(log);
appendln();
/*appendHeader("Plugin Information");
log = new LogListBlock();
for (Plugin plugin : plugins) {
log.putChild(plugin.getDescription().getName())
.put("Data folder", plugin.getDataFolder())
.put("Website", plugin.getDescription().getWebsite())
.put("Entry point", plugin.getDescription().getMain());
}
append(log);
appendln();*/
}
private void appendWorldInformation(List<World> worlds) {
appendHeader("Worlds");
LogListBlock log = new LogListBlock();
int i = 0;
for (World world : worlds) {
int loadedChunkCount = world.getLoadedChunks().length;
LogListBlock worldLog = log.putChild(world.getName() + " (" + i + ")");
LogListBlock infoLog = worldLog.putChild("Information");
LogListBlock entitiesLog = worldLog.putChild("Entities");
infoLog.put("Seed", world.getSeed());
infoLog.put("Environment", world.getEnvironment().toString());
infoLog.put("Player count", world.getPlayers().size());
infoLog.put("Entity count", world.getEntities().size());
infoLog.put("Loaded chunk count", loadedChunkCount);
infoLog.put("Spawn location", world.getSpawnLocation());
infoLog.put("Raw time", world.getFullTime());
Map<Class<? extends Entity>, Integer> entityCounts =
new HashMap<Class<? extends Entity>, Integer>();
// Collect entities
for (Entity entity : world.getEntities()) {
Class<? extends Entity> cls = entity.getClass();
if (entityCounts.containsKey(cls)) {
entityCounts.put(cls, entityCounts.get(cls) + 1);
} else {
entityCounts.put(cls, 1);
}
}
// Print entities
for (Map.Entry<Class<? extends Entity>, Integer> entry
: entityCounts.entrySet()) {
entitiesLog.put(entry.getKey().getSimpleName(),
"%d [%f/chunk]",
entry.getValue(),
(float) (entry.getValue() / (double) loadedChunkCount));
}
i++;
}
append(log);
appendln();
}
private void appendWorldConfigurations(WorldGuardPlugin plugin, List<World> worlds,
GlobalRegionManager regionMgr, ConfigurationManager mgr) {
appendHeader("World Configurations");
LogListBlock log = new LogListBlock();
int i = 0;
for (World world : worlds) {
LogListBlock worldLog = log.putChild(world.getName() + " (" + i + ")");
LogListBlock infoLog = worldLog.putChild("Information");
LogListBlock configLog = worldLog.putChild("Configuration");
LogListBlock blacklistLog = worldLog.putChild("Blacklist");
LogListBlock regionsLog = worldLog.putChild("Region manager");
infoLog.put("Configuration file", (new File(plugin.getDataFolder(), "worlds/"
+ world.getName() + "/config.yml")).getAbsoluteFile());
infoLog.put("Blacklist file", (new File(plugin.getDataFolder(), "worlds/"
+ world.getName() + "/blacklist.txt")).getAbsoluteFile());
infoLog.put("Regions file", (new File(plugin.getDataFolder(), "worlds/"
+ world.getName() + "/regions.yml")).getAbsoluteFile());
WorldConfiguration config = mgr.get(world);
Class<? extends WorldConfiguration> cls = config.getClass();
for (Field field : cls.getFields()) {
try {
Object val = field.get(config);
configLog.put(field.getName(), String.valueOf(val));
} catch (IllegalArgumentException e) {
e.printStackTrace();
} catch (IllegalAccessException ignore) {
}
}
if (config.getBlacklist() == null) {
blacklistLog.put("State", "DISABLED");
} else {
blacklistLog.put("State", "Enabled");
blacklistLog.put("Number of items",
config.getBlacklist().getItemCount());
blacklistLog.put("Is whitelist",
config.getBlacklist().isWhitelist());
}
RegionManager worldRegions = regionMgr.get(world);
regionsLog.put("Type", worldRegions.getClass().getCanonicalName());
regionsLog.put("Number of regions", worldRegions.getRegions().size());
LogListBlock globalRegionLog = regionsLog.putChild("Global region");
ProtectedRegion globalRegion = worldRegions.matchRegion("__global__");
if (globalRegion == null) {
globalRegionLog.put("Status", "UNDEFINED");
} else {
for (Flag<?> flag : DefaultFlag.getFlags()) {
if (flag instanceof StateFlag) {
globalRegionLog.put(flag.getName(),
globalRegion.getFlag(flag));
}
}
}
}
append(log);
appendln();
}
public void write(File file) throws IOException {
FileWriter writer = null;
BufferedWriter out;
try {
writer = new FileWriter(file);
out = new BufferedWriter(writer);
out.write(output.toString());
out.close();
} finally {
if (writer != null) {
try {
writer.close();
} catch (IOException ignore) {
}
}
}
}
@Override
public String toString() {
return output.toString();
}
}

View File

@ -0,0 +1,78 @@
/*
* WorldGuard, a suite of tools for Minecraft
* Copyright (C) sk89q <http://www.sk89q.com>
* Copyright (C) WorldGuard team and contributors
*
* This program is free software: you can redistribute it and/or modify it
* under the terms of the GNU Lesser General Public License as published by the
* Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License
* for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package com.sk89q.worldguard.bukkit.util;
import com.sk89q.worldguard.bukkit.WorldGuardPlugin;
import org.bukkit.metadata.FixedMetadataValue;
import org.bukkit.metadata.MetadataValue;
import org.bukkit.metadata.Metadatable;
import javax.annotation.Nullable;
import java.util.List;
/**
* Utility methods for dealing with metadata on entities.
*
* <p>WorldGuard is placed as the owner of all values.</p>
*/
public final class WGMetadata {
private WGMetadata() {
}
/**
* Add some metadata to a target.
*
* @param target the target
* @param key the key
* @param value the value
*/
public static void put(Metadatable target, String key, Object value) {
target.setMetadata(key, new FixedMetadataValue(WorldGuardPlugin.inst(), value));
}
/**
* Get the (first) metadata value on the given target that has the given
* key and is of the given class type.
*
* @param target the target
* @param key the key
* @param expected the type of the value
* @param <T> the type of the value
* @return a value, or {@code null} if one does not exists
*/
@Nullable
@SuppressWarnings("unchecked")
public static <T> T getIfPresent(Metadatable target, String key, Class<T> expected) {
List<MetadataValue> values = target.getMetadata(key);
WorldGuardPlugin owner = WorldGuardPlugin.inst();
for (MetadataValue value : values) {
if (value.getOwningPlugin() == owner) {
Object v = value.value();
if (expected.isInstance(v)) {
return (T) v;
}
}
}
return null;
}
}

View File

@ -17,15 +17,15 @@
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package com.sk89q.worldguard.internal.event;
package com.sk89q.worldguard.domains;
/**
* Represents a possible act upon an object.
* Indicates the level of membership.
*/
public enum Interaction {
public enum Association {
PLACE,
BREAK,
INTERACT
OWNER,
MEMBER,
NON_MEMBER
}

View File

@ -19,83 +19,263 @@
package com.sk89q.worldguard.domains;
import com.google.common.collect.ImmutableMap;
import com.sk89q.squirrelid.Profile;
import com.sk89q.squirrelid.cache.ProfileCache;
import com.sk89q.worldguard.LocalPlayer;
import com.sk89q.worldguard.util.ChangeTracked;
import javax.annotation.Nullable;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Iterator;
import java.util.List;
import java.util.Set;
import java.util.concurrent.CopyOnWriteArraySet;
import java.util.UUID;
public class DefaultDomain implements Domain {
private final Set<String> groups;
private final Set<String> players;
public DefaultDomain() {
this.groups = new CopyOnWriteArraySet<String>();
this.players = new CopyOnWriteArraySet<String>();
import static com.google.common.base.Preconditions.checkNotNull;
/**
* A combination of a {@link PlayerDomain} and a {@link GroupDomain}.
*/
public class DefaultDomain implements Domain, ChangeTracked {
private PlayerDomain playerDomain = new PlayerDomain();
private GroupDomain groupDomain = new GroupDomain();
/**
* Get the domain that holds the players.
*
* @return a domain
*/
public PlayerDomain getPlayerDomain() {
return playerDomain;
}
/**
* Set a new player domain.
*
* @param playerDomain a domain
*/
public void setPlayerDomain(PlayerDomain playerDomain) {
checkNotNull(playerDomain);
this.playerDomain = playerDomain;
}
/**
* Set the domain that holds the groups.
*
* @return a domain
*/
public GroupDomain getGroupDomain() {
return groupDomain;
}
/**
* Set a new group domain.
*
* @param groupDomain a domain
*/
public void setGroupDomain(GroupDomain groupDomain) {
checkNotNull(groupDomain);
this.groupDomain = groupDomain;
}
/**
* Add the given player to the domain, identified by the player's name.
*
* @param name the name of the player
*/
public void addPlayer(String name) {
players.add(name.toLowerCase());
playerDomain.addPlayer(name);
}
public void addPlayer(LocalPlayer player) {
players.add(player.getName().toLowerCase());
}
/**
* Remove the given player from the domain, identified by the player's name.
*
* @param name the name of the player
*/
public void removePlayer(String name) {
players.remove(name.toLowerCase());
playerDomain.removePlayer(name);
}
/**
* Remove the given player from the domain, identified by the player's UUID.
*
* @param uuid the UUID of the player
*/
public void removePlayer(UUID uuid) {
playerDomain.removePlayer(uuid);
}
/**
* Add the given player to the domain, identified by the player's UUID.
*
* @param uniqueId the UUID of the player
*/
public void addPlayer(UUID uniqueId) {
playerDomain.addPlayer(uniqueId);
}
/**
* Remove the given player from the domain, identified by either the
* player's name, the player's unique ID, or both.
*
* @param player the player
*/
public void removePlayer(LocalPlayer player) {
players.remove(player.getName().toLowerCase());
playerDomain.removePlayer(player);
}
public void addGroup(String name) {
groups.add(name.toLowerCase());
/**
* Add the given player to the domain, identified by the player's UUID.
*
* @param player the player
*/
public void addPlayer(LocalPlayer player) {
playerDomain.addPlayer(player);
}
public void removeGroup(String name) {
groups.remove(name.toLowerCase());
/**
* Add all the entries from another domain.
*
* @param other the other domain
*/
public void addAll(DefaultDomain other) {
checkNotNull(other);
for (String player : other.getPlayers()) {
addPlayer(player);
}
for (UUID uuid : other.getUniqueIds()) {
addPlayer(uuid);
}
for (String group : other.getGroups()) {
addGroup(group);
}
}
public Set<String> getGroups() {
return groups;
/**
* Remove all the entries from another domain.
*
* @param other the other domain
*/
public void removeAll(DefaultDomain other) {
checkNotNull(other);
for (String player : other.getPlayers()) {
removePlayer(player);
}
for (UUID uuid : other.getUniqueIds()) {
removePlayer(uuid);
}
for (String group : other.getGroups()) {
removeGroup(group);
}
}
/**
* Get the set of player names.
*
* @return the set of player names
*/
public Set<String> getPlayers() {
return players;
return playerDomain.getPlayers();
}
/**
* Get the set of player UUIDs.
*
* @return the set of player UUIDs
*/
public Set<UUID> getUniqueIds() {
return playerDomain.getUniqueIds();
}
/**
* Add the name of the group to the domain.
*
* @param name the name of the group.
*/
public void addGroup(String name) {
groupDomain.addGroup(name);
}
/**
* Remove the given group from the domain.
*
* @param name the name of the group
*/
public void removeGroup(String name) {
groupDomain.removeGroup(name);
}
/**
* Get the set of group names.
*
* @return the set of group names
*/
public Set<String> getGroups() {
return groupDomain.getGroups();
}
@Override
public boolean contains(LocalPlayer player) {
if (contains(player.getName())) {
return true;
}
return playerDomain.contains(player) || groupDomain.contains(player);
}
for (String group : groups) {
if (player.hasGroup(group)) {
return true;
}
}
return false;
@Override
public boolean contains(UUID uniqueId) {
return playerDomain.contains(uniqueId);
}
@Override
public boolean contains(String playerName) {
return players.contains(playerName.toLowerCase());
return playerDomain.contains(playerName);
}
@Override
public int size() {
return groups.size() + players.size();
return groupDomain.size() + playerDomain.size();
}
@Override
public void clear() {
playerDomain.clear();
groupDomain.clear();
}
public void removeAll() {
clear();
}
public String toPlayersString() {
return toPlayersString(null);
}
@SuppressWarnings("deprecation")
public String toPlayersString(@Nullable ProfileCache cache) {
StringBuilder str = new StringBuilder();
List<String> output = new ArrayList<String>(players);
List<String> output = new ArrayList<String>();
for (String name : playerDomain.getPlayers()) {
output.add("name:" + name);
}
if (cache != null) {
ImmutableMap<UUID, Profile> results = cache.getAllPresent(playerDomain.getUniqueIds());
for (UUID uuid : playerDomain.getUniqueIds()) {
Profile profile = results.get(uuid);
if (profile != null) {
output.add(profile.getName() + "*");
} else {
output.add("uuid:" + uuid);
}
}
} else {
for (UUID uuid : playerDomain.getUniqueIds()) {
output.add("uuid:" + uuid);
}
}
Collections.sort(output, String.CASE_INSENSITIVE_ORDER);
for (Iterator<String> it = output.iterator(); it.hasNext();) {
str.append(it.next());
@ -108,7 +288,7 @@ public String toPlayersString() {
public String toGroupsString() {
StringBuilder str = new StringBuilder();
for (Iterator<String> it = groups.iterator(); it.hasNext(); ) {
for (Iterator<String> it = groupDomain.getGroups().iterator(); it.hasNext(); ) {
str.append("*");
str.append(it.next());
if (it.hasNext()) {
@ -117,26 +297,51 @@ public String toGroupsString() {
}
return str.toString();
}
public String toUserFriendlyString() {
StringBuilder str = new StringBuilder();
if (players.size() > 0) {
if (playerDomain.size() > 0) {
str.append(toPlayersString());
}
if (groups.size() > 0) {
if (groupDomain.size() > 0) {
if (str.length() > 0) {
str.append("; ");
}
str.append(toGroupsString());
}
return str.toString();
}
public void removeAll() {
groups.clear();
players.clear();
public String toUserFriendlyString(ProfileCache cache) {
StringBuilder str = new StringBuilder();
if (playerDomain.size() > 0) {
str.append(toPlayersString(cache));
}
if (groupDomain.size() > 0) {
if (str.length() > 0) {
str.append("; ");
}
str.append(toGroupsString());
}
return str.toString();
}
@Override
public boolean isDirty() {
return playerDomain.isDirty() || groupDomain.isDirty();
}
@Override
public void setDirty(boolean dirty) {
playerDomain.setDirty(dirty);
groupDomain.setDirty(dirty);
}
}

View File

@ -21,21 +21,53 @@
import com.sk89q.worldguard.LocalPlayer;
import java.util.UUID;
/**
* A domain contains a list of memberships.
*/
public interface Domain {
/**
* Returns true if a domain contains a player.
*
* @param player The player to check
* @param player the player to check
* @return whether this domain contains {@code player}
*/
boolean contains(LocalPlayer player);
/**
* Returns true if a domain contains a player.<br />
* This method doesn't check for groups!
* Returns true if a domain contains a player.
*
* <p>This method doesn't check for groups!</p>
*
* @param uniqueId the UUID of the user
* @return whether this domain contains a player by that name
*/
boolean contains(UUID uniqueId);
/**
* Returns true if a domain contains a player.
*
* <p>This method doesn't check for groups!</p>
*
* @param playerName The name of the player to check
* @return whether this domain contains a player by that name
* @deprecated names are deprecated in MC 1.7+ in favor of UUIDs
*/
@Deprecated
boolean contains(String playerName);
/**
* Get the number of entries.
*
* @return the number of entries
*/
int size();
/**
* Remove all entries.
*/
void clear();
}

View File

@ -19,12 +19,18 @@
package com.sk89q.worldguard.domains;
import java.util.LinkedHashSet;
import java.util.Set;
import com.sk89q.worldguard.LocalPlayer;
import java.util.LinkedHashSet;
import java.util.Set;
import java.util.UUID;
/**
* @deprecated not used by WorldGuard and not maintained
*/
@Deprecated
public class DomainCollection implements Domain {
private Set<Domain> domains;
public DomainCollection() {
@ -39,10 +45,16 @@ public void remove(Domain domain) {
domains.remove(domain);
}
@Override
public int size() {
return domains.size();
}
@Override
public void clear() {
domains.clear();
}
@Override
public boolean contains(LocalPlayer player) {
for (Domain domain : domains) {
@ -54,6 +66,17 @@ public boolean contains(LocalPlayer player) {
return false;
}
@Override
public boolean contains(UUID uniqueId) {
for (Domain domain : domains) {
if (domain.contains(uniqueId)) {
return true;
}
}
return false;
}
@Override
public boolean contains(String playerName) {
for (Domain domain : domains) {
@ -64,4 +87,5 @@ public boolean contains(String playerName) {
return false;
}
}

View File

@ -19,28 +19,69 @@
package com.sk89q.worldguard.domains;
import java.util.Arrays;
import java.util.LinkedHashSet;
import java.util.Set;
import com.sk89q.worldguard.LocalPlayer;
import com.sk89q.worldguard.util.ChangeTracked;
public class GroupDomain implements Domain {
private Set<String> groups;
import java.util.Collections;
import java.util.Set;
import java.util.UUID;
import java.util.concurrent.CopyOnWriteArraySet;
import static com.google.common.base.Preconditions.checkArgument;
import static com.google.common.base.Preconditions.checkNotNull;
/**
* Contains groups in a domain.
*/
public class GroupDomain implements Domain, ChangeTracked {
private final Set<String> groups = new CopyOnWriteArraySet<String>();
private boolean dirty = true;
/**
* Create a new instance.
*/
public GroupDomain() {
this.groups = new LinkedHashSet<String>();
}
/**
* Create a new instance.
*
* @param groups an array of groups
*/
public GroupDomain(String[] groups) {
this.groups = new LinkedHashSet<String>(Arrays.asList(groups));
checkNotNull(groups);
for (String group : groups) {
addGroup(group);
}
}
/**
* Add the name of the group to the domain.
*
* @param name the name of the group.
*/
public void addGroup(String name) {
groups.add(name);
checkNotNull(name);
checkArgument(!name.trim().isEmpty(), "Can't add empty group name");
setDirty(true);
groups.add(name.trim().toLowerCase());
}
/**
* Remove the given group from the domain.
*
* @param name the name of the group
*/
public void removeGroup(String name) {
checkNotNull(name);
setDirty(true);
groups.remove(name.trim().toLowerCase());
}
@Override
public boolean contains(LocalPlayer player) {
checkNotNull(player);
for (String group : groups) {
if (player.hasGroup(group)) {
return true;
@ -50,12 +91,43 @@ public boolean contains(LocalPlayer player) {
return false;
}
/**
* Get the set of group names.
*
* @return the set of group names
*/
public Set<String> getGroups() {
return Collections.unmodifiableSet(groups);
}
@Override
public boolean contains(UUID uniqueId) {
return false; // GroupDomains can't contain UUIDs
}
@Override
public boolean contains(String playerName) {
return false; // GroupDomains can't contain player names.
}
@Override
public int size() {
return groups.size();
}
@Override
public void clear() {
groups.clear();
}
@Override
public boolean isDirty() {
return dirty;
}
@Override
public void setDirty(boolean dirty) {
this.dirty = dirty;
}
}

View File

@ -19,40 +19,170 @@
package com.sk89q.worldguard.domains;
import java.util.HashSet;
import java.util.Set;
import com.sk89q.worldguard.LocalPlayer;
import com.sk89q.worldguard.util.ChangeTracked;
public class PlayerDomain implements Domain {
private Set<String> players;
import java.util.Collections;
import java.util.Set;
import java.util.UUID;
import java.util.concurrent.CopyOnWriteArraySet;
import static com.google.common.base.Preconditions.checkArgument;
import static com.google.common.base.Preconditions.checkNotNull;
/**
* Stores players (only) in a domain.
*/
public class PlayerDomain implements Domain, ChangeTracked {
private final Set<UUID> uniqueIds = new CopyOnWriteArraySet<UUID>();
private final Set<String> names = new CopyOnWriteArraySet<String>();
private boolean dirty = true;
/**
* Create a new instance.
*/
public PlayerDomain() {
this.players = new HashSet<String>();
}
public PlayerDomain(String[] players) {
this.players = new HashSet<String>();
for (String name : players) {
this.players.add(name.toLowerCase());
/**
* Create a new instance with the given names.
*
* @param names an array of names
* @deprecated names are deprecated in favor of UUIDs in MC 1.7+
*/
@Deprecated
public PlayerDomain(String[] names) {
for (String name : names) {
addPlayer(name);
}
}
/**
* Add the given player to the domain, identified by the player's name.
*
* @param name the name of the player
*/
public void addPlayer(String name) {
players.add(name.toLowerCase());
checkNotNull(name);
checkArgument(!name.trim().isEmpty(), "Can't add empty player name");
setDirty(true);
names.add(name.trim().toLowerCase());
// Trim because some names contain spaces (previously valid Minecraft
// names) and we cannot store these correctly in the SQL storage
// implementations
}
/**
* Add the given player to the domain, identified by the player's UUID.
*
* @param uniqueId the UUID of the player
*/
public void addPlayer(UUID uniqueId) {
checkNotNull(uniqueId);
setDirty(true);
uniqueIds.add(uniqueId);
}
/**
* Add the given player to the domain, identified by the player's UUID.
*
* @param player the player
*/
public void addPlayer(LocalPlayer player) {
checkNotNull(player);
setDirty(true);
addPlayer(player.getUniqueId());
}
/**
* Remove the given player from the domain, identified by the player's name.
*
* @param name the name of the player
*/
public void removePlayer(String name) {
checkNotNull(name);
setDirty(true);
names.remove(name.trim().toLowerCase());
}
/**
* Remove the given player from the domain, identified by the player's UUID.
*
* @param uuid the UUID of the player
*/
public void removePlayer(UUID uuid) {
checkNotNull(uuid);
uniqueIds.remove(uuid);
}
/**
* Remove the given player from the domain, identified by either the
* player's name, the player's unique ID, or both.
*
* @param player the player
*/
public void removePlayer(LocalPlayer player) {
checkNotNull(player);
removePlayer(player.getName());
removePlayer(player.getUniqueId());
}
@Override
public boolean contains(LocalPlayer player) {
return contains(player.getName());
checkNotNull(player);
return contains(player.getName()) || contains(player.getUniqueId());
}
/**
* Get the set of player names.
*
* @return the set of player names
*/
public Set<String> getPlayers() {
return Collections.unmodifiableSet(names);
}
/**
* Get the set of player UUIDs.
*
* @return the set of player UUIDs
*/
public Set<UUID> getUniqueIds() {
return Collections.unmodifiableSet(uniqueIds);
}
@Override
public boolean contains(UUID uniqueId) {
checkNotNull(uniqueId);
return uniqueIds.contains(uniqueId);
}
@Override
public boolean contains(String playerName) {
return players.contains(playerName.toLowerCase());
checkNotNull(playerName);
return names.contains(playerName.trim().toLowerCase());
}
@Override
public int size() {
return players.size();
return names.size() + uniqueIds.size();
}
@Override
public void clear() {
uniqueIds.clear();
names.clear();
}
@Override
public boolean isDirty() {
return dirty;
}
@Override
public void setDirty(boolean dirty) {
this.dirty = dirty;
}
}

View File

@ -1,100 +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.internal.cause;
import org.bukkit.block.Block;
import org.bukkit.entity.Entity;
import org.bukkit.entity.Player;
import javax.annotation.Nullable;
import java.util.ArrayList;
import java.util.List;
/**
* Utility methods to handle {@code Cause}s.
*/
public final class Causes {
private Causes() {
}
/**
* Get the first player that is in the list of causes.
*
* @param causes a list of causes, where the originating causes are at the beginning
* @return the player or null
*/
@Nullable
public static Player getInvolvedPlayer(List<? extends Cause<?>> causes) {
for (Cause cause : causes) {
if (cause instanceof PlayerCause) {
return ((PlayerCause) cause).get();
}
}
return null;
}
/**
* Test whether the list of causes may indicate that a player was part of
* the cause, directly or indirectly.
*
* <p>An indirect cause would be a dispenser, for example.</p>
*
* @param causes a list of cuases
* @return true if the event involved a player
*/
public static boolean mayInvolvePlayer(List<? extends Cause<?>> causes) {
for (Cause<?> cause : causes) {
if (cause instanceof PlayerCause || cause instanceof BlockCause) {
return true; // This needs to be made smarter later
}
}
return false;
}
/**
* Create a list of causes from a list of objects representing causes.
*
* @param cause an array of causes, where the originating causes are at the beginning
* @return a list of causes, where the originating causes are at the beginning
*/
public static List<? extends Cause<?>> create(Object ... cause) {
List<Cause<?>> causes = new ArrayList<Cause<?>>(cause.length);
for (Object o : cause) {
if (o == null) {
continue;
}
if (o instanceof Player) {
causes.add(new PlayerCause((Player) o));
} else if (o instanceof Block) {
causes.add(new BlockCause((Block) o));
} else if (o instanceof Entity) {
causes.add(new EntityCause((Entity) o));
} else {
causes.add(new UnknownCause(o));
}
}
return causes;
}
}

View File

@ -1,90 +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.internal.listener;
import com.sk89q.worldguard.blacklist.event.BlockBreakBlacklistEvent;
import com.sk89q.worldguard.blacklist.event.BlockPlaceBlacklistEvent;
import com.sk89q.worldguard.blacklist.event.ItemDestroyWithBlacklistEvent;
import com.sk89q.worldguard.bukkit.WorldConfiguration;
import com.sk89q.worldguard.bukkit.WorldGuardPlugin;
import com.sk89q.worldguard.internal.cause.Causes;
import com.sk89q.worldguard.internal.event.BlockInteractEvent;
import org.bukkit.block.Block;
import org.bukkit.entity.Player;
import org.bukkit.event.EventHandler;
import static com.sk89q.worldguard.bukkit.BukkitUtil.createTarget;
import static com.sk89q.worldguard.bukkit.BukkitUtil.toVector;
/**
* Handle events that need to be processed by the blacklist.
*/
public class BlacklistListener extends AbstractListener {
/**
* Construct the listener.
*
* @param plugin an instance of WorldGuardPlugin
*/
public BlacklistListener(WorldGuardPlugin plugin) {
super(plugin);
}
@EventHandler(ignoreCancelled = true)
public void handleBlockInteract(BlockInteractEvent event) {
Player player = Causes.getInvolvedPlayer(event.getCauses());
Block target = event.getTarget();
WorldConfiguration wcfg = getWorldConfig(player);
// Blacklist guard
if (wcfg.getBlacklist() == null) {
return;
}
if (player != null) {
switch (event.getInteraction()) {
case BREAK:
if (!wcfg.getBlacklist().check(
new BlockBreakBlacklistEvent(getPlugin().wrapPlayer(player), toVector(target), createTarget(target)), false, false)) {
event.setCancelled(true);
return;
}
if (!wcfg.getBlacklist().check(
new ItemDestroyWithBlacklistEvent(getPlugin().wrapPlayer(player), toVector(target), createTarget(player.getItemInHand())), false, false)) {
event.setCancelled(true);
return;
}
break;
case PLACE:
if (!wcfg.getBlacklist().check(
new BlockPlaceBlacklistEvent(getPlugin().wrapPlayer(player), toVector(target), createTarget(target)), false, false)) {
event.setCancelled(true);
return;
}
break;
}
}
}
}

View File

@ -1,76 +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.internal.listener;
import com.sk89q.worldguard.bukkit.WorldConfiguration;
import com.sk89q.worldguard.bukkit.WorldGuardPlugin;
import com.sk89q.worldguard.internal.cause.Causes;
import com.sk89q.worldguard.internal.event.Interaction;
import com.sk89q.worldguard.internal.event.BlockInteractEvent;
import org.bukkit.ChatColor;
import org.bukkit.block.Block;
import org.bukkit.entity.Player;
import org.bukkit.event.EventHandler;
/**
* Handle events that need to be processed by the chest protection.
*/
public class ChestProtectionListener extends AbstractListener {
/**
* Construct the listener.
*
* @param plugin an instance of WorldGuardPlugin
*/
public ChestProtectionListener(WorldGuardPlugin plugin) {
super(plugin);
}
@EventHandler(ignoreCancelled = true)
public void handleBlockInteract(BlockInteractEvent event) {
Player player = Causes.getInvolvedPlayer(event.getCauses());
Block target = event.getTarget();
WorldConfiguration wcfg = getWorldConfig(player);
// Early guard
if (!wcfg.signChestProtection) {
return;
}
if (player != null) {
if (wcfg.isChestProtected(target, player)) {
player.sendMessage(ChatColor.DARK_RED + "This chest is protected.");
event.setCancelled(true);
return;
}
if (event.getInteraction() == Interaction.PLACE) {
if (wcfg.getChestProtection().isChest(target.getTypeId())) {
if (wcfg.isAdjacentChestProtected(target, player)) {
player.sendMessage(ChatColor.DARK_RED + "This spot is for a chest that you don't have permission for.");
event.setCancelled(true);
return;
}
}
}
}
}
}

View File

@ -1,72 +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.internal.listener;
import com.sk89q.worldguard.bukkit.WorldGuardPlugin;
import com.sk89q.worldguard.internal.cause.Causes;
import com.sk89q.worldguard.internal.event.Interaction;
import com.sk89q.worldguard.internal.event.BlockInteractEvent;
import org.bukkit.ChatColor;
import org.bukkit.block.Block;
import org.bukkit.command.CommandSender;
import org.bukkit.entity.Player;
import org.bukkit.event.EventHandler;
/**
* Handle events that need to be processed by region protection.
*/
public class RegionProtectionListener extends AbstractListener {
/**
* Construct the listener.
*
* @param plugin an instance of WorldGuardPlugin
*/
public RegionProtectionListener(WorldGuardPlugin plugin) {
super(plugin);
}
private void tellErrorMessage(CommandSender sender, Object subject) {
sender.sendMessage(ChatColor.DARK_RED + "You don't have permission for this area.");
}
@EventHandler(ignoreCancelled = true)
public void handleBlockInteract(BlockInteractEvent event) {
Player player = Causes.getInvolvedPlayer(event.getCauses());
Block target = event.getTarget();
if (player != null) {
if (!getPlugin().getGlobalRegionManager().canBuild(player, target)) {
tellErrorMessage(player, target);
event.setCancelled(true);
return;
}
if (event.getInteraction() != Interaction.INTERACT) {
if (!getPlugin().getGlobalRegionManager().canConstruct(player, target)) {
tellErrorMessage(player, target);
event.setCancelled(true);
return;
}
}
}
}
}

View File

@ -0,0 +1,59 @@
/*
* 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.internal.util.sql;
import java.sql.PreparedStatement;
import java.sql.SQLException;
public final class StatementUtils {
private StatementUtils() {
}
/**
* Creates a comma separated list of PreparedStatement place holders
*
* @param length The number of wildcards to create
* @return A string with {@code length} wildcards for usage in a PreparedStatement
*/
public static String preparePlaceHolders(int length) {
StringBuilder builder = new StringBuilder();
for (int i = 0; i < length;) {
builder.append("?");
if (++i < length) {
builder.append(",");
}
}
return builder.toString();
}
/**
* Adds all of the parsed values to the PreparedStatement
*
* @param preparedStatement The preparedStanement to add to
* @param values The values to set
* @throws SQLException see {@link PreparedStatement#setString(int, String)}
*/
public static void setValues(PreparedStatement preparedStatement, String... values) throws SQLException {
for (int i = 0; i < values.length; i++) {
preparedStatement.setString(i + 1, values[i]);
}
}
}

View File

@ -0,0 +1,111 @@
/*
* WorldGuard, a suite of tools for Minecraft
* Copyright (C) sk89q <http://www.sk89q.com>
* Copyright (C) WorldGuard team and contributors
*
* This program is free software: you can redistribute it and/or modify it
* under the terms of the GNU Lesser General Public License as published by the
* Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License
* for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package com.sk89q.worldguard.protection;
import com.sk89q.worldguard.LocalPlayer;
import com.sk89q.worldguard.protection.association.RegionAssociable;
import com.sk89q.worldguard.protection.flags.DefaultFlag;
import com.sk89q.worldguard.protection.flags.Flag;
import com.sk89q.worldguard.protection.flags.RegionGroup;
import com.sk89q.worldguard.protection.flags.RegionGroupFlag;
import com.sk89q.worldguard.protection.flags.StateFlag;
import com.sk89q.worldguard.protection.flags.StateFlag.State;
import javax.annotation.Nullable;
import static com.google.common.base.Preconditions.checkNotNull;
import static com.sk89q.worldguard.protection.flags.StateFlag.test;
public abstract class AbstractRegionSet implements ApplicableRegionSet {
@Override
@Deprecated
public boolean canBuild(LocalPlayer player) {
checkNotNull(player);
return test(queryState(player, DefaultFlag.BUILD));
}
@Override
@Deprecated
public boolean canConstruct(LocalPlayer player) {
checkNotNull(player);
final RegionGroup flag = getFlag(DefaultFlag.CONSTRUCT, player);
return RegionGroupFlag.isMember(this, flag, player);
}
@Override
public boolean testState(@Nullable RegionAssociable subject, StateFlag... flags) {
return test(queryState(subject, flags));
}
@Nullable
@Override
public State queryState(@Nullable RegionAssociable subject, StateFlag... flags) {
State value = null;
for (StateFlag flag : flags) {
value = StateFlag.combine(value, queryValue(subject, flag));
if (value == State.DENY) {
break;
}
}
return value;
}
@Override
@Deprecated
public boolean allows(StateFlag flag) {
checkNotNull(flag);
if (flag == DefaultFlag.BUILD) {
throw new IllegalArgumentException("Can't use build flag with allows()");
}
return test(queryState(null, flag));
}
@Override
@Deprecated
public boolean allows(StateFlag flag, @Nullable LocalPlayer player) {
checkNotNull(flag);
if (flag == DefaultFlag.BUILD) {
throw new IllegalArgumentException("Can't use build flag with allows()");
}
return test(queryState(player, flag));
}
@Override
@Deprecated
@Nullable
public <T extends Flag<V>, V> V getFlag(T flag, @Nullable LocalPlayer groupPlayer) {
return queryValue(groupPlayer, flag);
}
@Override
@Deprecated
@Nullable
public <T extends Flag<V>, V> V getFlag(T flag) {
return getFlag(flag, null);
}
}

View File

@ -20,66 +20,165 @@
package com.sk89q.worldguard.protection;
import com.sk89q.worldguard.LocalPlayer;
import com.sk89q.worldguard.protection.flags.*;
import com.sk89q.worldguard.bukkit.RegionQuery;
import com.sk89q.worldguard.protection.association.RegionAssociable;
import com.sk89q.worldguard.protection.flags.DefaultFlag;
import com.sk89q.worldguard.protection.flags.Flag;
import com.sk89q.worldguard.protection.flags.RegionGroup;
import com.sk89q.worldguard.protection.flags.StateFlag;
import com.sk89q.worldguard.protection.flags.StateFlag.State;
import com.sk89q.worldguard.protection.managers.RegionManager;
import com.sk89q.worldguard.protection.regions.ProtectedRegion;
import java.util.*;
import javax.annotation.Nullable;
import java.util.Collection;
import java.util.Set;
/**
* Represents a set of regions for a particular point or area and the rules
* that are represented by that set. An instance of this can be used to
* query the value of a flag or check if a player can build in the respective
* region or point. This object contains the list of applicable regions and so
* the expensive search of regions that are in the desired area has already
* been completed.
*
* @author sk89q
* Represents the effective set of flags, owners, and members for a given
* spatial query.
*
* <p>An instance of this can be created using the spatial query methods
* available on {@link RegionManager}.</p>
*/
public class ApplicableRegionSet implements Iterable<ProtectedRegion> {
private Collection<ProtectedRegion> applicable;
private ProtectedRegion globalRegion;
public interface ApplicableRegionSet extends Iterable<ProtectedRegion> {
/**
* Construct the object.
*
* @param applicable The regions contained in this set
* @param globalRegion The global region, set aside for special handling.
* Return whether this region set is a virtual set. A virtual set
* does not contain real results.
*
* <p>A virtual result may be returned if region data failed to load or
* there was some special exception (i.e. the region bypass permission).
* </p>
*
* <p>Be sure to check the value of this flag if an instance of this
* interface is being retrieved from {@link RegionQuery} as it may
* return an instance of {@link PermissiveRegionSet} or
* {@link FailedLoadRegionSet}, among other possibilities.</p>
*
* @return true if loaded
* @see FailedLoadRegionSet
*/
public ApplicableRegionSet(Collection<ProtectedRegion> applicable,
ProtectedRegion globalRegion) {
this.applicable = applicable;
this.globalRegion = globalRegion;
}
/**
* Checks if a player can build in an area.
*
* @param player The player to check
* @return build ability
*/
public boolean canBuild(LocalPlayer player) {
return internalGetState(DefaultFlag.BUILD, player, null);
}
public boolean canConstruct(LocalPlayer player) {
final RegionGroup flag = getFlag(DefaultFlag.CONSTRUCT, player);
return RegionGroupFlag.isMember(this, flag, player);
}
boolean isVirtual();
/**
* Checks if a player can use buttons and such in an area.
*
* @param player The player to check
* @return able to use items
* @deprecated This method seems to be the opposite of its name
* Tests whether the {@link DefaultFlag#BUILD} flag or membership
* requirements permit the given player.
*
* <p>If there are several relevant flags (i.e. in addition to
* {@code BUILD}, such as {@link DefaultFlag#SLEEP} when the target
* object is a bed), then
* {@link #testBuild(RegionAssociable, StateFlag...)} should be used.</p>
*
* @param player the player to check
* @return true if permitted
* @deprecated use {@link #testBuild(RegionAssociable, StateFlag...)}
*/
@Deprecated
public boolean canUse(LocalPlayer player) {
return !allows(DefaultFlag.USE, player)
&& !canBuild(player);
}
boolean canBuild(LocalPlayer player);
/**
* Test whether the given flags evaluate to {@code ALLOW}, implicitly also
* considering the {@link DefaultFlag#BUILD} flag.
*
* <p>This method is equivalent to calling
* {@link #testState(RegionAssociable, StateFlag...)} with {@code flags} plus
* the {@code BUILD} flag.</p>
*
* @param subject the subject
* @param flags zero or more flags
* @return true if permission is granted
* @see #queryState(RegionAssociable, StateFlag...)
*/
boolean testBuild(RegionAssociable subject, StateFlag... flags);
/**
* Test whether the (effective) value for a list of state flags equals
* {@code ALLOW}.
*
* <p>{@code subject} can be non-null to satisfy region group requirements,
* otherwise it will be assumed that the caller that is not a member of any
* regions. (Flags on a region can be changed so that they only apply
* to certain users.) The subject argument is required if the
* {@link DefaultFlag#BUILD} flag is in the list of flags.</p>
*
* @param subject an optional subject, which would be used to determine the region groups that apply
* @param flags a list of flags to check
* @return true if the result was {@code ALLOW}
* @see #queryState(RegionAssociable, StateFlag...)
*/
boolean testState(@Nullable RegionAssociable subject, StateFlag... flags);
/**
* Get the (effective) value for a list of state flags. The rules of
* states is observed here; that is, {@code DENY} overrides {@code ALLOW},
* and {@code ALLOW} overrides {@code NONE}. One flag may override another.
*
* <p>{@code subject} can be non-null to satisfy region group requirements,
* otherwise it will be assumed that the caller that is not a member of any
* regions. (Flags on a region can be changed so that they only apply
* to certain users.) The subject argument is required if the
* {@link DefaultFlag#BUILD} flag is in the list of flags.</p>
*
* @param subject an optional subject, which would be used to determine the region groups that apply
* @param flags a list of flags to check
* @return a state
*/
@Nullable
State queryState(@Nullable RegionAssociable subject, StateFlag... flags);
/**
* Get the effective value for a flag. If there are multiple values
* (for example, multiple overlapping regions with
* the same priority may have the same flag set), then the selected
* (or "winning") value will depend on the flag type.
*
* <p>Only some flag types actually have a strategy for picking the
* "best value." For most types, the actual value that is chosen to be
* returned is undefined (it could be any value). As of writing, the only
* type of flag that actually has a strategy for picking a value is the
* {@link StateFlag}.</p>
*
* <p>{@code subject} can be non-null to satisfy region group requirements,
* otherwise it will be assumed that the caller that is not a member of any
* regions. (Flags on a region can be changed so that they only apply
* to certain users.) The subject argument is required if the
* {@link DefaultFlag#BUILD} flag is the flag being queried.</p>
*
* @param subject an optional subject, which would be used to determine the region group to apply
* @param flag the flag
* @return a value, which could be {@code null}
*/
@Nullable
<V> V queryValue(@Nullable RegionAssociable subject, Flag<V> flag);
/**
* Get the effective values for a flag, returning a collection of all
* values. It is up to the caller to determine which value, if any,
* from the collection will be used.
*
* <p>{@code subject} can be non-null to satisfy region group requirements,
* otherwise it will be assumed that the caller that is not a member of any
* regions. (Flags on a region can be changed so that they only apply
* to certain users.) The subject argument is required if the
* {@link DefaultFlag#BUILD} flag is the flag being queried.</p>
*
* @param subject an optional subject, which would be used to determine the region group to apply
* @param flag the flag
* @return a collection of values
*/
<V> Collection<V> queryAllValues(@Nullable RegionAssociable subject, Flag<V> flag);
/**
* Test whether the construct flag evaluates true for the given player.
*
* @param player the player
* @return true if true
* @deprecated The {@code CONSTRUCT} flag is being removed and is no longer
* needed because flags now support groups assigned to them.
*/
@Deprecated
boolean canConstruct(LocalPlayer player);
/**
* Gets the state of a state flag. This cannot be used for the build flag.
@ -87,317 +186,79 @@ public boolean canUse(LocalPlayer player) {
* @param flag flag to check
* @return whether it is allowed
* @throws IllegalArgumentException if the build flag is given
* @deprecated use {@link #queryState(RegionAssociable, StateFlag...)} instead
*/
public boolean allows(StateFlag flag) {
if (flag == DefaultFlag.BUILD) {
throw new IllegalArgumentException("Can't use build flag with allows()");
}
return internalGetState(flag, null, null);
}
@Deprecated
boolean allows(StateFlag flag);
/**
* Gets the state of a state flag. This cannot be used for the build flag.
*
*
* @param flag flag to check
* @param player player (used by some flags)
* @return whether the state is allows for it
* @throws IllegalArgumentException if the build flag is given
* @deprecated use {@link #queryState(RegionAssociable, StateFlag...)} instead
*/
public boolean allows(StateFlag flag, LocalPlayer player) {
if (flag == DefaultFlag.BUILD) {
throw new IllegalArgumentException("Can't use build flag with allows()");
}
return internalGetState(flag, null, player);
}
@Deprecated
boolean allows(StateFlag flag, @Nullable LocalPlayer player);
/**
* Indicates whether a player is an owner of all regions in this set.
*
* @param player player
* Test whether a player is an owner of all regions in this set.
*
* @param player the player
* @return whether the player is an owner of all regions
*/
public boolean isOwnerOfAll(LocalPlayer player) {
for (ProtectedRegion region : applicable) {
if (!region.isOwner(player)) {
return false;
}
}
return true;
}
boolean isOwnerOfAll(LocalPlayer player);
/**
* Indicates whether a player is an owner or member of all regions in
* this set.
*
* @param player player
* Test whether a player is an owner or member of all regions in this set.
*
* @param player the player
* @return whether the player is a member of all regions
*/
public boolean isMemberOfAll(LocalPlayer player) {
for (ProtectedRegion region : applicable) {
if (!region.isMember(player)) {
return false;
}
}
return true;
}
/**
* Checks to see if a flag is permitted.
*
* @param flag flag to check
* @param player null to not check owners and members
* @param groupPlayer player to use for the group flag check
* @return the allow/deny state for the flag
*/
private boolean internalGetState(StateFlag flag, LocalPlayer player,
LocalPlayer groupPlayer) {
boolean found = false;
boolean hasFlagDefined = false;
boolean allowed = false; // Used for ALLOW override
boolean def = flag.getDefault();
// Handle defaults
if (globalRegion != null) {
State globalState = globalRegion.getFlag(flag);
// The global region has this flag set
if (globalState != null) {
// Build flag is very special
if (player != null && globalRegion.hasMembersOrOwners()) {
def = globalRegion.isMember(player) && (globalState == State.ALLOW);
} else {
def = (globalState == State.ALLOW);
}
} else {
// Build flag is very special
if (player != null && globalRegion.hasMembersOrOwners()) {
def = globalRegion.isMember(player);
}
}
}
// The player argument is used if and only if the flag is the build
// flag -- in which case, if there are any regions in this area, we
// default to FALSE, otherwise true if there are no defined regions.
// However, other flags are different -- if there are regions defined,
// we default to the global region value.
if (player == null) {
allowed = def;
}
int lastPriority = Integer.MIN_VALUE;
// The algorithm is as follows:
// While iterating through the list of regions, if an entry disallows
// the flag, then put it into the needsClear set. If an entry allows
// the flag and it has a parent, then its parent is put into hasCleared.
// In the situation that the child is reached before the parent, upon
// the parent being reached, even if the parent disallows, because the
// parent will be in hasCleared, permission will be allowed. In the
// other case, where the parent is reached first, if it does not allow
// permissions, it will be placed into needsClear. If a child of
// the parent is reached later, the parent will be removed from
// needsClear. At the end, if needsClear is not empty, that means that
// permission should not be given. If a parent has multiple children
// and one child does not allow permissions, then it will be placed into
// needsClear just like as if was a parent.
Set<ProtectedRegion> needsClear = new HashSet<ProtectedRegion>();
Set<ProtectedRegion> hasCleared = new HashSet<ProtectedRegion>();
for (ProtectedRegion region : applicable) {
// Ignore lower priority regions
if (hasFlagDefined && region.getPriority() < lastPriority) {
break;
}
lastPriority = region.getPriority();
// Ignore non-build regions
if (player != null
&& region.getFlag(DefaultFlag.PASSTHROUGH) == State.ALLOW) {
continue;
}
// Check group permissions
if (groupPlayer != null && flag.getRegionGroupFlag() != null) {
RegionGroup group = region.getFlag(flag.getRegionGroupFlag());
if (group == null) {
group = flag.getRegionGroupFlag().getDefault();
}
if (!RegionGroupFlag.isMember(region, group, groupPlayer)) {
continue;
}
}
State v = region.getFlag(flag);
// Allow DENY to override everything
if (v == State.DENY) {
return false;
}
// Forget about regions that allow it, although make sure the
// default state is now to allow
if (v == State.ALLOW) {
allowed = true;
found = true;
hasFlagDefined = true;
continue;
}
// For the build flag, the flags are conditional and are based
// on membership, so we have to check for parent-child
// relationships
if (player != null) {
hasFlagDefined = true;
if (hasCleared.contains(region)) {
// Already cleared, so do nothing
} else {
if (!region.isMember(player)) {
needsClear.add(region);
} else {
// Need to clear all parents
clearParents(needsClear, hasCleared, region);
}
}
}
found = true;
}
return !found ? def :
(allowed || (player != null && needsClear.size() == 0));
}
/**
* Clear a region's parents for isFlagAllowed().
*
* @param needsClear The regions that should be cleared
* @param hasCleared The regions already cleared
* @param region The region to start from
*/
private void clearParents(Set<ProtectedRegion> needsClear,
Set<ProtectedRegion> hasCleared, ProtectedRegion region) {
ProtectedRegion parent = region.getParent();
while (parent != null) {
if (!needsClear.remove(parent)) {
hasCleared.add(parent);
}
parent = parent.getParent();
}
}
/**
* @see #getFlag(com.sk89q.worldguard.protection.flags.Flag, com.sk89q.worldguard.LocalPlayer)
* @param flag flag to check
* @return value of the flag
*/
public <T extends Flag<V>, V> V getFlag(T flag) {
return getFlag(flag, null);
}
boolean isMemberOfAll(LocalPlayer player);
/**
* Gets the value of a flag. Do not use this for state flags
* (use {@link #allows(StateFlag, LocalPlayer)} for that).
*
*
* @param flag the flag to check
* @return value of the flag, which may be null
* @deprecated Use {@link #queryValue(RegionAssociable, Flag)} instead. There
* is no difference in functionality.
*/
@Deprecated
@Nullable
<T extends Flag<V>, V> V getFlag(T flag);
/**
* Gets the value of a flag. Do not use this for state flags
* (use {@link #allows(StateFlag, LocalPlayer)} for that).
*
* @param flag flag to check
* @param groupPlayer player to check {@link RegionGroup}s against
* @return value of the flag
* @return value of the flag, which may be null
* @throws IllegalArgumentException if a StateFlag is given
* @deprecated Use {@link #queryValue(RegionAssociable, Flag)} instead. There
* is no difference in functionality.
*/
public <T extends Flag<V>, V> V getFlag(T flag, LocalPlayer groupPlayer) {
/*
if (flag instanceof StateFlag) {
throw new IllegalArgumentException("Cannot use StateFlag with getFlag()");
}
*/
@Deprecated
@Nullable
<T extends Flag<V>, V> V getFlag(T flag, @Nullable LocalPlayer groupPlayer);
int lastPriority = 0;
boolean found = false;
Map<ProtectedRegion, V> needsClear = new HashMap<ProtectedRegion, V>();
Set<ProtectedRegion> hasCleared = new HashSet<ProtectedRegion>();
for (ProtectedRegion region : applicable) {
// Ignore lower priority regions
if (found && region.getPriority() < lastPriority) {
break;
}
// Check group permissions
if (groupPlayer != null && flag.getRegionGroupFlag() != null) {
RegionGroup group = region.getFlag(flag.getRegionGroupFlag());
if (group == null) {
group = flag.getRegionGroupFlag().getDefault();
}
if (!RegionGroupFlag.isMember(region, group, groupPlayer)) {
continue;
}
}
if (hasCleared.contains(region)) {
// Already cleared, so do nothing
} else if (region.getFlag(flag) != null) {
clearParents(needsClear, hasCleared, region);
needsClear.put(region, region.getFlag(flag));
found = true;
}
lastPriority = region.getPriority();
}
if (!needsClear.isEmpty()) {
return needsClear.values().iterator().next();
} else {
if (globalRegion != null) {
V gFlag = globalRegion.getFlag(flag);
if (gFlag != null) return gFlag;
}
return null;
}
}
/**
* Clear a region's parents for getFlag().
*
* @param needsClear The regions that should be cleared
* @param hasCleared The regions already cleared
* @param region The region to start from
*/
private void clearParents(Map<ProtectedRegion, ?> needsClear,
Set<ProtectedRegion> hasCleared, ProtectedRegion region) {
ProtectedRegion parent = region.getParent();
while (parent != null) {
if (needsClear.remove(parent) == null) {
hasCleared.add(parent);
}
parent = parent.getParent();
}
}
/**
* Get the number of regions that are included.
*
* @return the size of this ApplicbleRegionSet
*
* @return the number of contained regions
*/
public int size() {
return applicable.size();
}
int size();
/**
* Get an iterator of affected regions.
* Get an immutable set of regions that are included in this set.
*
* @return a set of regions
*/
public Iterator<ProtectedRegion> iterator() {
return applicable.iterator();
}
Set<ProtectedRegion> getRegions();
}

View File

@ -0,0 +1,122 @@
/*
* WorldGuard, a suite of tools for Minecraft
* Copyright (C) sk89q <http://www.sk89q.com>
* Copyright (C) WorldGuard team and contributors
*
* This program is free software: you can redistribute it and/or modify it
* under the terms of the GNU Lesser General Public License as published by the
* Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License
* for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package com.sk89q.worldguard.protection;
import com.google.common.collect.ImmutableList;
import com.google.common.collect.Iterators;
import com.sk89q.worldguard.LocalPlayer;
import com.sk89q.worldguard.protection.association.RegionAssociable;
import com.sk89q.worldguard.protection.flags.DefaultFlag;
import com.sk89q.worldguard.protection.flags.Flag;
import com.sk89q.worldguard.protection.flags.StateFlag;
import com.sk89q.worldguard.protection.flags.StateFlag.State;
import com.sk89q.worldguard.protection.regions.ProtectedRegion;
import org.bukkit.ChatColor;
import javax.annotation.Nullable;
import java.util.Collection;
import java.util.Collections;
import java.util.Iterator;
import java.util.Set;
/**
* A region set that is to be used when region data has failed. Operations
* are blocked.
*/
public class FailedLoadRegionSet extends AbstractRegionSet {
private static final FailedLoadRegionSet INSTANCE = new FailedLoadRegionSet();
private final String denyMessage = ChatColor.RED + "Region data for WorldGuard failed to load for this world, so " +
"everything has been protected as a precaution. Please inform a server administrator.";
private final Collection<String> denyMessageCollection = ImmutableList.of(denyMessage);
private FailedLoadRegionSet() {
}
@Override
public boolean isVirtual() {
return true;
}
@Override
public boolean testBuild(RegionAssociable subject, StateFlag... flags) {
return false;
}
@SuppressWarnings("unchecked")
@Nullable
@Override
public <V> V queryValue(@Nullable RegionAssociable subject, Flag<V> flag) {
if (flag == DefaultFlag.BUILD) {
return (V) State.DENY;
} else if (flag == DefaultFlag.DENY_MESSAGE) {
return (V) denyMessage;
}
return flag.getDefault();
}
@SuppressWarnings("unchecked")
@Override
public <V> Collection<V> queryAllValues(@Nullable RegionAssociable subject, Flag<V> flag) {
if (flag == DefaultFlag.BUILD) {
return (Collection<V>) ImmutableList.of(State.DENY);
} else if (flag == DefaultFlag.DENY_MESSAGE) {
return (Collection<V>) denyMessageCollection;
}
V fallback = flag.getDefault();
return fallback != null ? ImmutableList.of(fallback) : (Collection<V>) ImmutableList.of();
}
@Override
public boolean isOwnerOfAll(LocalPlayer player) {
return false;
}
@Override
public boolean isMemberOfAll(LocalPlayer player) {
return false;
}
@Override
public int size() {
return 0;
}
@Override
public Set<ProtectedRegion> getRegions() {
return Collections.emptySet();
}
@Override
public Iterator<ProtectedRegion> iterator() {
return Iterators.emptyIterator();
}
/**
* Get an instance.
*
* @return an instance
*/
public static FailedLoadRegionSet getInstance() {
return INSTANCE;
}
}

Some files were not shown because too many files have changed in this diff Show More