From ad1c10a3e9220e8c8dd40e3a399928e9abfd3230 Mon Sep 17 00:00:00 2001 From: sk89q Date: Wed, 13 Aug 2014 14:06:37 -0700 Subject: [PATCH] Reorganize Bukkit portion of the region API. --- .../worldguard/bukkit/WorldGuardPlugin.java | 9 +- .../bukkit/commands/RegionCommands.java | 2 +- .../bukkit/commands/WorldGuardCommands.java | 5 +- .../listener/RegionProtectionListener.java | 12 +- .../AbstractPermissionModel.java | 3 +- .../RegionPermissionModel.java | 13 +- ...onQuery.java => ProtectedRegionQuery.java} | 14 +- .../protection/GlobalRegionManager.java | 271 +++++++++++++----- 8 files changed, 234 insertions(+), 95 deletions(-) rename src/main/java/com/sk89q/worldguard/bukkit/{ => permission}/AbstractPermissionModel.java (93%) rename src/main/java/com/sk89q/worldguard/bukkit/{ => permission}/RegionPermissionModel.java (94%) rename src/main/java/com/sk89q/worldguard/bukkit/util/{RegionQuery.java => ProtectedRegionQuery.java} (84%) diff --git a/src/main/java/com/sk89q/worldguard/bukkit/WorldGuardPlugin.java b/src/main/java/com/sk89q/worldguard/bukkit/WorldGuardPlugin.java index 1b2fcc15..b1605983 100644 --- a/src/main/java/com/sk89q/worldguard/bukkit/WorldGuardPlugin.java +++ b/src/main/java/com/sk89q/worldguard/bukkit/WorldGuardPlugin.java @@ -64,11 +64,12 @@ 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.util.UnresolvedNamesException; import com.sk89q.worldguard.protection.util.migrator.MigrationException; import com.sk89q.worldguard.protection.util.migrator.UUIDMigrator; -import com.sk89q.worldguard.protection.util.UnresolvedNamesException; -import com.sk89q.worldguard.protection.managers.RegionManager; import com.sk89q.worldguard.util.FatalConfigurationLoadingException; +import org.bukkit.Bukkit; import org.bukkit.ChatColor; import org.bukkit.Location; import org.bukkit.World; @@ -190,7 +191,7 @@ public void run() { getLogger().info("Loading region data..."); globalRegionManager = new GlobalRegionManager(this); - globalRegionManager.preload(); + globalRegionManager.loadAll(Bukkit.getServer().getWorlds()); migrateRegionUniqueIds(); // Migrate to UUIDs } catch (FatalConfigurationLoadingException e) { @@ -281,7 +282,7 @@ public void onDisable() { getLogger().log(Level.WARNING, "Some tasks failed while waiting for remaining tasks to finish", e); } - globalRegionManager.unload(); + globalRegionManager.unloadAll(); configuration.unload(); this.getServer().getScheduler().cancelTasks(this); } diff --git a/src/main/java/com/sk89q/worldguard/bukkit/commands/RegionCommands.java b/src/main/java/com/sk89q/worldguard/bukkit/commands/RegionCommands.java index fff71fe0..e4928023 100644 --- a/src/main/java/com/sk89q/worldguard/bukkit/commands/RegionCommands.java +++ b/src/main/java/com/sk89q/worldguard/bukkit/commands/RegionCommands.java @@ -35,7 +35,7 @@ import com.sk89q.worldedit.bukkit.selections.Selection; import com.sk89q.worldguard.LocalPlayer; import com.sk89q.worldguard.bukkit.LoggerToChatHandler; -import com.sk89q.worldguard.bukkit.RegionPermissionModel; +import com.sk89q.worldguard.bukkit.permission.RegionPermissionModel; import com.sk89q.worldguard.bukkit.WorldConfiguration; import com.sk89q.worldguard.bukkit.WorldGuardPlugin; import com.sk89q.worldguard.protection.ApplicableRegionSet; diff --git a/src/main/java/com/sk89q/worldguard/bukkit/commands/WorldGuardCommands.java b/src/main/java/com/sk89q/worldguard/bukkit/commands/WorldGuardCommands.java index 22991901..17e7dd7c 100644 --- a/src/main/java/com/sk89q/worldguard/bukkit/commands/WorldGuardCommands.java +++ b/src/main/java/com/sk89q/worldguard/bukkit/commands/WorldGuardCommands.java @@ -30,6 +30,7 @@ import com.sk89q.worldguard.bukkit.WorldGuardPlugin; import com.sk89q.worldguard.util.PastebinPoster; import com.sk89q.worldguard.util.PastebinPoster.PasteCallback; +import org.bukkit.Bukkit; import org.bukkit.ChatColor; import org.bukkit.command.CommandSender; import org.bukkit.entity.Player; @@ -77,9 +78,9 @@ public void reload(CommandContext args, CommandSender sender) throws CommandExce try { plugin.getGlobalStateManager().unload(); - plugin.getGlobalRegionManager().unload(); + plugin.getGlobalRegionManager().unloadAll(); plugin.getGlobalStateManager().load(); - plugin.getGlobalRegionManager().preload(); + plugin.getGlobalRegionManager().loadAll(Bukkit.getServer().getWorlds()); // WGBukkit.cleanCache(); sender.sendMessage("WorldGuard configuration reloaded."); } catch (Throwable t) { diff --git a/src/main/java/com/sk89q/worldguard/bukkit/listener/RegionProtectionListener.java b/src/main/java/com/sk89q/worldguard/bukkit/listener/RegionProtectionListener.java index d800380e..66300fe3 100644 --- a/src/main/java/com/sk89q/worldguard/bukkit/listener/RegionProtectionListener.java +++ b/src/main/java/com/sk89q/worldguard/bukkit/listener/RegionProtectionListener.java @@ -29,7 +29,7 @@ import com.sk89q.worldguard.bukkit.event.entity.UseEntityEvent; import com.sk89q.worldguard.bukkit.util.Entities; import com.sk89q.worldguard.bukkit.util.Materials; -import com.sk89q.worldguard.bukkit.util.RegionQuery; +import com.sk89q.worldguard.bukkit.util.ProtectedRegionQuery; import com.sk89q.worldguard.protection.flags.DefaultFlag; import com.sk89q.worldguard.protection.managers.RegionManager; import org.bukkit.ChatColor; @@ -98,7 +98,7 @@ public void onPlaceBlock(PlaceBlockEvent event) { Material type = event.getEffectiveMaterial(); if (player != null) { - RegionQuery query = new RegionQuery(getPlugin(), player); + ProtectedRegionQuery query = new ProtectedRegionQuery(getPlugin(), player); boolean canPlace; // Flint and steel, fire charge @@ -139,7 +139,7 @@ public void onUseBlock(UseBlockEvent event) { Material type = event.getEffectiveMaterial(); if (player != null) { - RegionQuery query = new RegionQuery(getPlugin(), player); + ProtectedRegionQuery query = new ProtectedRegionQuery(getPlugin(), player); boolean canUse; // Inventory blocks (CHEST_ACCESS) @@ -179,7 +179,7 @@ public void onSpawnEntity(SpawnEntityEvent event) { EntityType type = event.getEffectiveType(); if (player != null) { - RegionQuery query = new RegionQuery(getPlugin(), player); + ProtectedRegionQuery query = new ProtectedRegionQuery(getPlugin(), player); boolean canSpawn; if (Entities.isVehicle(type)) { @@ -202,7 +202,7 @@ public void onDestroyEntity(DestroyEntityEvent event) { EntityType type = event.getEntity().getType(); if (player != null) { - RegionQuery query = new RegionQuery(getPlugin(), player); + ProtectedRegionQuery query = new ProtectedRegionQuery(getPlugin(), player); boolean canDestroy; if (Entities.isVehicle(type)) { @@ -224,7 +224,7 @@ public void onUseEntity(UseEntityEvent event) { Location target = event.getTarget(); if (player != null) { - RegionQuery query = new RegionQuery(getPlugin(), player); + ProtectedRegionQuery query = new ProtectedRegionQuery(getPlugin(), player); boolean canUse = query.canBuild(target) || query.allows(DefaultFlag.USE, target); if (!canUse) { diff --git a/src/main/java/com/sk89q/worldguard/bukkit/AbstractPermissionModel.java b/src/main/java/com/sk89q/worldguard/bukkit/permission/AbstractPermissionModel.java similarity index 93% rename from src/main/java/com/sk89q/worldguard/bukkit/AbstractPermissionModel.java rename to src/main/java/com/sk89q/worldguard/bukkit/permission/AbstractPermissionModel.java index a885e2ba..ff7538f3 100644 --- a/src/main/java/com/sk89q/worldguard/bukkit/AbstractPermissionModel.java +++ b/src/main/java/com/sk89q/worldguard/bukkit/permission/AbstractPermissionModel.java @@ -17,8 +17,9 @@ * along with this program. If not, see . */ -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; diff --git a/src/main/java/com/sk89q/worldguard/bukkit/RegionPermissionModel.java b/src/main/java/com/sk89q/worldguard/bukkit/permission/RegionPermissionModel.java similarity index 94% rename from src/main/java/com/sk89q/worldguard/bukkit/RegionPermissionModel.java rename to src/main/java/com/sk89q/worldguard/bukkit/permission/RegionPermissionModel.java index 3e0ba0fe..3807468b 100644 --- a/src/main/java/com/sk89q/worldguard/bukkit/RegionPermissionModel.java +++ b/src/main/java/com/sk89q/worldguard/bukkit/permission/RegionPermissionModel.java @@ -17,14 +17,15 @@ * along with this program. If not, see . */ -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"); diff --git a/src/main/java/com/sk89q/worldguard/bukkit/util/RegionQuery.java b/src/main/java/com/sk89q/worldguard/bukkit/util/ProtectedRegionQuery.java similarity index 84% rename from src/main/java/com/sk89q/worldguard/bukkit/util/RegionQuery.java rename to src/main/java/com/sk89q/worldguard/bukkit/util/ProtectedRegionQuery.java index 12f4f747..9d26992a 100644 --- a/src/main/java/com/sk89q/worldguard/bukkit/util/RegionQuery.java +++ b/src/main/java/com/sk89q/worldguard/bukkit/util/ProtectedRegionQuery.java @@ -24,6 +24,7 @@ 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.GlobalRegionManager; import com.sk89q.worldguard.protection.flags.StateFlag; import com.sk89q.worldguard.protection.managers.RegionManager; @@ -35,17 +36,21 @@ import static com.sk89q.worldguard.bukkit.BukkitUtil.toVector; -public class RegionQuery { +public class ProtectedRegionQuery { private final ConfigurationManager config; private final GlobalRegionManager globalManager; @Nullable private final LocalPlayer localPlayer; - public RegionQuery(WorldGuardPlugin plugin, @Nullable Player player) { + public ProtectedRegionQuery(WorldGuardPlugin plugin, @Nullable Player player) { + this(plugin, player != null ? plugin.wrapPlayer(player) : null); + } + + public ProtectedRegionQuery(WorldGuardPlugin plugin, @Nullable LocalPlayer player) { this.config = plugin.getGlobalStateManager(); this.globalManager = plugin.getGlobalRegionManager(); - this.localPlayer = player != null ? plugin.wrapPlayer(player) : null; + this.localPlayer = player; } public boolean canBuild(Location location) { @@ -76,7 +81,8 @@ public boolean canConstruct(Location location) { return true; } else { RegionManager manager = globalManager.get(location.getWorld()); - return manager.getApplicableRegions(BukkitUtil.toVector(location)).canConstruct(localPlayer); + ApplicableRegionSet result = manager.getApplicableRegions(BukkitUtil.toVector(location)); + return result.canBuild(localPlayer) && result.canConstruct(localPlayer); } } diff --git a/src/main/java/com/sk89q/worldguard/protection/GlobalRegionManager.java b/src/main/java/com/sk89q/worldguard/protection/GlobalRegionManager.java index 2810df23..651d6f9e 100644 --- a/src/main/java/com/sk89q/worldguard/protection/GlobalRegionManager.java +++ b/src/main/java/com/sk89q/worldguard/protection/GlobalRegionManager.java @@ -21,10 +21,9 @@ import com.sk89q.worldedit.Vector2D; 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.util.ProtectedRegionQuery; import com.sk89q.worldguard.protection.flags.StateFlag; import com.sk89q.worldguard.protection.managers.RegionManager; import org.bukkit.Chunk; @@ -35,146 +34,272 @@ import javax.annotation.Nullable; import java.util.ArrayList; +import java.util.Collection; +import java.util.Collections; import java.util.List; import static com.google.common.base.Preconditions.checkNotNull; -import static com.sk89q.worldguard.bukkit.BukkitUtil.toVector; +/** + * A global region manager loads, saves and caches region data for zero or + * more worlds at a time. + * + *

This class is thread safe and its contents can be accessed from + * multiple concurrent threads.

+ */ public class GlobalRegionManager { private final WorldGuardPlugin plugin; - private final ConfigurationManager config; private final ManagerContainer container; + /** + * Create a new instance. + * + * @param plugin the plugin + */ public GlobalRegionManager(WorldGuardPlugin plugin) { this.plugin = plugin; - config = plugin.getGlobalStateManager(); + + ConfigurationManager config = plugin.getGlobalStateManager(); container = new ManagerContainer(config); } + /** + * Load the region data for a world if it has not been loaded already. + * + *

This method is called by WorldGuard and should not be called + * by other plugins.

+ * + * @param world the world + * @return a region manager, either returned from the cache or newly loaded + */ @Nullable public RegionManager load(World world) { checkNotNull(world); + RegionManager manager = container.load(world.getName()); + if (manager != null) { + // Bias the region data for loaded chunks List positions = new ArrayList(); for (Chunk chunk : world.getLoadedChunks()) { positions.add(new Vector2D(chunk.getX(), chunk.getZ())); } manager.loadChunks(positions); } + return manager; } - public void preload() { - for (World world : plugin.getServer().getWorlds()) { + /** + * Load the region data for a list of worlds. + * + *

This method is called by WorldGuard and should not be called + * by other plugins.

+ * + * @param worlds a list of worlds + */ + public void loadAll(Collection worlds) { + checkNotNull(worlds); + + for (World world : worlds) { load(world); } } + /** + * Unload the region data for a world. + * + * @param world a world + */ public void unload(World world) { - unload(world.getName()); - } - - public void unload(String name) { - container.unload(name); - } - - public void unload() { - container.unloadAll(); + checkNotNull(world); + + container.unload(world.getName()); } + /** + * Unload all region data for all worlds that region data has + * been loaded for. + */ public void unloadAll() { container.unloadAll(); } + /** + * Get the region manager for a world if one exists. + * + *

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.

+ * + * @param world the world + * @return a region manager, or {@code null} if one is not availale + */ @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 getLoaded() { - return container.getLoaded(); + return Collections.unmodifiableList(container.getLoaded()); } + /** + * Create a new region query with no player. + * + * @return a new query + */ + public ProtectedRegionQuery createAnonymousQuery() { + return new ProtectedRegionQuery(plugin, (Player) null); + } + + /** + * Create a new region query. + * + * @param player a player, or {@code null} + * @return a new query + */ + public ProtectedRegionQuery createQuery(@Nullable Player player) { + return new ProtectedRegionQuery(plugin, player); + } + + /** + * Create a new region query. + * + * @param player a player, or {@code null} + * @return a new query + */ + private ProtectedRegionQuery createQuery(@Nullable LocalPlayer player) { + return new ProtectedRegionQuery(plugin, player); + } + + /** + * Test whether the given player has region protection bypass permission. + * + * @param player the player + * @param world the world + * @return true if a bypass is permitted + * @deprecated use {@link #createQuery(Player)} + */ + @Deprecated public boolean hasBypass(LocalPlayer player, World world) { return player.hasPermission("worldguard.region.bypass." + world.getName()); } + /** + * Test whether the given player has region protection bypass permission. + * + * @param player the player + * @param world the world + * @return true if a bypass is permitted + * @deprecated use {@link #createQuery(Player)} + */ + @Deprecated public boolean hasBypass(Player player, World world) { return plugin.hasPermission(player, "worldguard.region.bypass." + world.getName()); } + /** + * Test whether the player can build (place, use, destroy blocks and + * entities) at the given position, considering only the build flag + * and the region's members. + * + *

This method is not an absolute test as to whether WorldGuard + * would allow or block an event because this method doesn't + * consider flags (i.e. chest-access flags when concerning a chest) or + * other modules in WorldGuard (i.e chest protection).

+ * + * @param player the player + * @param block the block + * @return true if a bypass is permitted + * @deprecated use {@link #createQuery(Player)} + */ + @SuppressWarnings("deprecation") + @Deprecated public boolean canBuild(Player player, Block block) { return canBuild(player, block.getLocation()); } - public boolean canBuild(Player player, Location loc) { - World world = loc.getWorld(); - WorldConfiguration worldConfig = config.get(world); - - if (!worldConfig.useRegions) { - return true; - } - - LocalPlayer localPlayer = plugin.wrapPlayer(player); - - if (!hasBypass(player, world)) { - RegionManager mgr = get(world); - - if (mgr != null && !mgr.getApplicableRegions(BukkitUtil.toVector(loc)).canBuild(localPlayer)) { - return false; - } - } - - return true; + /** + * Test whether the player can build (place, use, destroy blocks and + * entities) at the given position, considering only the build flag + * and the region's members. + * + *

This method is not an absolute test as to whether WorldGuard + * would allow or block an event because this method doesn't + * consider flags (i.e. chest-access flags when concerning a chest) or + * other modules in WorldGuard (i.e chest protection).

+ * + * @param player the player + * @param location the location + * @return true if a bypass is permitted + * @deprecated use {@link #createQuery(Player)} + */ + @Deprecated + public boolean canBuild(Player player, Location location) { + return createQuery(player).canBuild(location); } + /** + * Test whether the player can place blocks at the given position. + * + * @param player the player + * @param block the block + * @return true if permitted + * @deprecated use {@link #createQuery(Player)} + */ + @Deprecated + @SuppressWarnings("deprecation") public boolean canConstruct(Player player, Block block) { return canConstruct(player, block.getLocation()); } - public boolean canConstruct(Player player, Location loc) { - World world = loc.getWorld(); - WorldConfiguration worldConfig = config.get(world); - - if (!worldConfig.useRegions) { - return true; - } - - LocalPlayer localPlayer = plugin.wrapPlayer(player); - - if (!hasBypass(player, world)) { - RegionManager mgr = get(world); - - if (mgr != null) { - final ApplicableRegionSet applicableRegions = mgr.getApplicableRegions(BukkitUtil.toVector(loc)); - if (!applicableRegions.canBuild(localPlayer)) { - return false; - } - if (!applicableRegions.canConstruct(localPlayer)) { - return false; - } - } - } - - return true; + /** + * Test whether the player can place blocks at the given position. + * + * @param player the player + * @param location the location + * @return true if permitted + * @deprecated use {@link #createQuery(Player)} + */ + @Deprecated + public boolean canConstruct(Player player, Location location) { + return createQuery(player).canConstruct(location); } - public boolean allows(StateFlag flag, Location loc) { - return allows(flag, loc, null); + /** + * Test the value of a state flag at a location. + * + * @param flag the flag + * @param location the location + * @return true if set to true + * @deprecated use {@link #createQuery(Player)} + */ + @Deprecated + @SuppressWarnings("deprecation") + public boolean allows(StateFlag flag, Location location) { + return allows(flag, location, null); } - public boolean allows(StateFlag flag, Location loc, @Nullable LocalPlayer player) { - World world = loc.getWorld(); - WorldConfiguration worldConfig = config.get(world); - - if (!worldConfig.useRegions) { - return true; - } - - RegionManager mgr = get(world); - return mgr == null || mgr.getApplicableRegions(toVector(loc)).allows(flag, player); + /** + * Test the value of a state flag at a location, using the player as the + * relevant actor. + * + * @param flag the flag + * @param location the location + * @param player the actor + * @return true if set to true + * @deprecated use {@link #createQuery(Player)} + */ + @Deprecated + public boolean allows(StateFlag flag, Location location, @Nullable LocalPlayer player) { + return createQuery(player).allows(flag, location); } }