From 28c538e981aa6e05657551d0e7eeaf200439bd18 Mon Sep 17 00:00:00 2001 From: sk89q Date: Thu, 14 Aug 2014 21:24:32 -0700 Subject: [PATCH] Refactor region commands and make the necessary ones run in the background. --- .../bukkit/commands/AsyncCommandHelper.java | 2 +- .../bukkit/commands/CommandUtils.java | 6 +- .../commands/FutureProgressListener.java | 4 +- .../commands/MessageFutureCallback.java | 6 +- .../bukkit/commands/MessageTimerTask.java | 2 +- .../bukkit/commands/ProtectionCommands.java | 4 +- .../bukkit/commands/RegionListEntry.java | 59 - .../MemberCommands.java} | 564 ++-- .../commands/{ => region}/RegionCommands.java | 2267 +++++++---------- .../{ => region}/RegionPrintoutBuilder.java | 6 +- ...Reload.java => RegionManagerReloader.java} | 6 +- ...nagerSave.java => RegionManagerSaver.java} | 6 +- .../permission/RegionPermissionModel.java | 16 + 13 files changed, 1228 insertions(+), 1720 deletions(-) delete mode 100644 src/main/java/com/sk89q/worldguard/bukkit/commands/RegionListEntry.java rename src/main/java/com/sk89q/worldguard/bukkit/commands/{RegionMemberCommands.java => region/MemberCommands.java} (60%) rename src/main/java/com/sk89q/worldguard/bukkit/commands/{ => region}/RegionCommands.java (53%) rename src/main/java/com/sk89q/worldguard/bukkit/commands/{ => region}/RegionPrintoutBuilder.java (97%) rename src/main/java/com/sk89q/worldguard/bukkit/commands/task/{RegionManagerReload.java => RegionManagerReloader.java} (87%) rename src/main/java/com/sk89q/worldguard/bukkit/commands/task/{RegionmanagerSave.java => RegionManagerSaver.java} (87%) diff --git a/src/main/java/com/sk89q/worldguard/bukkit/commands/AsyncCommandHelper.java b/src/main/java/com/sk89q/worldguard/bukkit/commands/AsyncCommandHelper.java index a3ebaabc..a12862f3 100644 --- a/src/main/java/com/sk89q/worldguard/bukkit/commands/AsyncCommandHelper.java +++ b/src/main/java/com/sk89q/worldguard/bukkit/commands/AsyncCommandHelper.java @@ -30,7 +30,7 @@ import static com.google.common.base.Preconditions.checkNotNull; -class AsyncCommandHelper { +public class AsyncCommandHelper { private final ListenableFuture future; private final WorldGuardPlugin plugin; diff --git a/src/main/java/com/sk89q/worldguard/bukkit/commands/CommandUtils.java b/src/main/java/com/sk89q/worldguard/bukkit/commands/CommandUtils.java index 1d0f7080..77876e3a 100644 --- a/src/main/java/com/sk89q/worldguard/bukkit/commands/CommandUtils.java +++ b/src/main/java/com/sk89q/worldguard/bukkit/commands/CommandUtils.java @@ -30,7 +30,7 @@ /** * Command-related utility methods. */ -final class CommandUtils { +public final class CommandUtils { private CommandUtils() { } @@ -41,7 +41,7 @@ private CommandUtils() { * @param owner the owner object * @return a name */ - static String getOwnerName(@Nullable Object owner) { + public static String getOwnerName(@Nullable Object owner) { if (owner == null) { return "?"; } else if (owner instanceof Player) { @@ -62,7 +62,7 @@ static String getOwnerName(@Nullable Object owner) { * @param sender the sender * @return a function */ - static Function messageFunction(final CommandSender sender) { + public static Function messageFunction(final CommandSender sender) { return new Function() { @Override public Object apply(@Nullable String s) { diff --git a/src/main/java/com/sk89q/worldguard/bukkit/commands/FutureProgressListener.java b/src/main/java/com/sk89q/worldguard/bukkit/commands/FutureProgressListener.java index 549aaa05..5680a6de 100644 --- a/src/main/java/com/sk89q/worldguard/bukkit/commands/FutureProgressListener.java +++ b/src/main/java/com/sk89q/worldguard/bukkit/commands/FutureProgressListener.java @@ -28,14 +28,14 @@ import static com.google.common.base.Preconditions.checkNotNull; -class FutureProgressListener implements Runnable { +public class FutureProgressListener implements Runnable { private static final Timer timer = new Timer(); private static final int MESSAGE_DELAY = 1000; private final MessageTimerTask task; - FutureProgressListener(CommandSender sender, String message) { + public FutureProgressListener(CommandSender sender, String message) { checkNotNull(sender); checkNotNull(message); diff --git a/src/main/java/com/sk89q/worldguard/bukkit/commands/MessageFutureCallback.java b/src/main/java/com/sk89q/worldguard/bukkit/commands/MessageFutureCallback.java index cb25126a..d07c04d8 100644 --- a/src/main/java/com/sk89q/worldguard/bukkit/commands/MessageFutureCallback.java +++ b/src/main/java/com/sk89q/worldguard/bukkit/commands/MessageFutureCallback.java @@ -28,7 +28,7 @@ import static com.google.common.base.Preconditions.checkNotNull; -class MessageFutureCallback implements FutureCallback { +public class MessageFutureCallback implements FutureCallback { private final WorldGuardPlugin plugin; private final CommandSender sender; @@ -57,7 +57,7 @@ public void onFailure(@Nullable Throwable throwable) { sender.sendMessage(ChatColor.RED + failure + ": " + plugin.convertThrowable(throwable)); } - static class Builder { + public static class Builder { private final WorldGuardPlugin plugin; private final CommandSender sender; @Nullable @@ -65,7 +65,7 @@ static class Builder { @Nullable private String failure; - Builder(WorldGuardPlugin plugin, CommandSender sender) { + public Builder(WorldGuardPlugin plugin, CommandSender sender) { checkNotNull(plugin); checkNotNull(sender); diff --git a/src/main/java/com/sk89q/worldguard/bukkit/commands/MessageTimerTask.java b/src/main/java/com/sk89q/worldguard/bukkit/commands/MessageTimerTask.java index b4554c09..ad3f9a49 100644 --- a/src/main/java/com/sk89q/worldguard/bukkit/commands/MessageTimerTask.java +++ b/src/main/java/com/sk89q/worldguard/bukkit/commands/MessageTimerTask.java @@ -25,7 +25,7 @@ import static com.google.common.base.Preconditions.checkNotNull; -class MessageTimerTask extends TimerTask { +public class MessageTimerTask extends TimerTask { private final CommandSender sender; private final String message; diff --git a/src/main/java/com/sk89q/worldguard/bukkit/commands/ProtectionCommands.java b/src/main/java/com/sk89q/worldguard/bukkit/commands/ProtectionCommands.java index 136a66b6..d0a6db7a 100644 --- a/src/main/java/com/sk89q/worldguard/bukkit/commands/ProtectionCommands.java +++ b/src/main/java/com/sk89q/worldguard/bukkit/commands/ProtectionCommands.java @@ -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") diff --git a/src/main/java/com/sk89q/worldguard/bukkit/commands/RegionListEntry.java b/src/main/java/com/sk89q/worldguard/bukkit/commands/RegionListEntry.java deleted file mode 100644 index 2620938a..00000000 --- a/src/main/java/com/sk89q/worldguard/bukkit/commands/RegionListEntry.java +++ /dev/null @@ -1,59 +0,0 @@ -/* - * WorldGuard, a suite of tools for Minecraft - * Copyright (C) sk89q - * 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 . - */ - -package com.sk89q.worldguard.bukkit.commands; - -/** - * Used for /rg list. - */ -class RegionListEntry implements Comparable { - - 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; - } - } - -} \ No newline at end of file diff --git a/src/main/java/com/sk89q/worldguard/bukkit/commands/RegionMemberCommands.java b/src/main/java/com/sk89q/worldguard/bukkit/commands/region/MemberCommands.java similarity index 60% rename from src/main/java/com/sk89q/worldguard/bukkit/commands/RegionMemberCommands.java rename to src/main/java/com/sk89q/worldguard/bukkit/commands/region/MemberCommands.java index f9732f02..3ea62fc6 100644 --- a/src/main/java/com/sk89q/worldguard/bukkit/commands/RegionMemberCommands.java +++ b/src/main/java/com/sk89q/worldguard/bukkit/commands/region/MemberCommands.java @@ -1,330 +1,234 @@ -/* - * WorldGuard, a suite of tools for Minecraft - * Copyright (C) sk89q - * 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 . - */ - -package com.sk89q.worldguard.bukkit.commands; - -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.worldguard.LocalPlayer; -import com.sk89q.worldguard.bukkit.WorldGuardPlugin; -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; - -// @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 = " ", - flags = "nw:", - 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 ."); - } - } - - String id = args.getString(0); - - RegionManager manager = plugin.getGlobalRegionManager().get(world); - ProtectedRegion region = manager.matchRegion(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()); - } - } - - // 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 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 = " ", - flags = "nw:", - 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 ."); - } - } - - String id = args.getString(0); - - RegionManager manager = plugin.getGlobalRegionManager().get(world); - ProtectedRegion region = manager.matchRegion(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 && 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 { - 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()); - } - } - } - - // 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 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 = " ", - flags = "naw:", - 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 ."); - } - } - - String id = args.getString(0); - - RegionManager manager = plugin.getGlobalRegionManager().get(world); - ProtectedRegion region = manager.matchRegion(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()); - } - } - - 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 = " ", - flags = "naw:", - 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 ."); - } - } - - String id = args.getString(0); - - RegionManager manager = plugin.getGlobalRegionManager().get(world); - ProtectedRegion region = manager.matchRegion(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()); - } - } - - 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"); - } -} +/* + * WorldGuard, a suite of tools for Minecraft + * Copyright (C) sk89q + * 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 . + */ + +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 = " ", + flags = "nw:", + desc = "Add a member to a region", + min = 2) + public void addMember(CommandContext args, CommandSender sender) throws CommandException { + 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 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 = " ", + flags = "nw:", + desc = "Add an owner to a region", + min = 2) + public void addOwner(CommandContext args, CommandSender sender) throws CommandException { + 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 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 = " ", + flags = "naw:", + desc = "Remove an owner to a region", + min = 1) + public void removeMember(CommandContext args, CommandSender sender) throws CommandException { + 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 = " ", + flags = "naw:", + desc = "Remove an owner to a region", + min = 1) + public void removeOwner(CommandContext args, CommandSender sender) throws CommandException { + 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"); + } +} diff --git a/src/main/java/com/sk89q/worldguard/bukkit/commands/RegionCommands.java b/src/main/java/com/sk89q/worldguard/bukkit/commands/region/RegionCommands.java similarity index 53% rename from src/main/java/com/sk89q/worldguard/bukkit/commands/RegionCommands.java rename to src/main/java/com/sk89q/worldguard/bukkit/commands/region/RegionCommands.java index 265f448a..3003196c 100644 --- a/src/main/java/com/sk89q/worldguard/bukkit/commands/RegionCommands.java +++ b/src/main/java/com/sk89q/worldguard/bukkit/commands/region/RegionCommands.java @@ -1,1311 +1,956 @@ -/* - * WorldGuard, a suite of tools for Minecraft - * Copyright (C) sk89q - * 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 . - */ - -package com.sk89q.worldguard.bukkit.commands; - -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.worldedit.BlockVector; -import com.sk89q.worldedit.Location; -import com.sk89q.worldedit.Vector; -import com.sk89q.worldedit.bukkit.BukkitUtil; -import com.sk89q.worldedit.bukkit.WorldEditPlugin; -import com.sk89q.worldedit.bukkit.selections.CuboidSelection; -import com.sk89q.worldedit.bukkit.selections.Polygonal2DSelection; -import com.sk89q.worldedit.bukkit.selections.Selection; -import com.sk89q.worldguard.LocalPlayer; -import com.sk89q.worldguard.bukkit.WorldConfiguration; -import com.sk89q.worldguard.bukkit.WorldGuardPlugin; -import com.sk89q.worldguard.bukkit.commands.task.RegionAdd; -import com.sk89q.worldguard.bukkit.commands.task.RegionManagerReload; -import com.sk89q.worldguard.bukkit.commands.task.RegionmanagerSave; -import com.sk89q.worldguard.bukkit.permission.RegionPermissionModel; -import com.sk89q.worldguard.bukkit.util.LoggerToChatHandler; -import com.sk89q.worldguard.protection.ApplicableRegionSet; -import com.sk89q.worldguard.protection.flags.DefaultFlag; -import com.sk89q.worldguard.protection.flags.Flag; -import com.sk89q.worldguard.protection.flags.InvalidFlagFormat; -import com.sk89q.worldguard.protection.flags.RegionGroup; -import com.sk89q.worldguard.protection.flags.RegionGroupFlag; -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 com.sk89q.worldguard.protection.regions.ProtectedRegion.CircularInheritanceException; -import com.sk89q.worldguard.protection.util.DomainInputResolver.UserLocatorPolicy; -import com.sk89q.worldguard.protection.util.migrator.MigrationException; -import com.sk89q.worldguard.protection.util.migrator.UUIDMigrator; -import org.bukkit.Bukkit; -import org.bukkit.ChatColor; -import org.bukkit.World; -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.logging.Level; -import java.util.logging.Logger; - -/** - * Implements the /region commands for WorldGuard. - */ -public final class RegionCommands { - - private final WorldGuardPlugin plugin; - - public RegionCommands(WorldGuardPlugin plugin) { - this.plugin = plugin; - } - - /** - * Get the permission model to lookup permissions. - * - * @param sender the sender - * @return the permission model - */ - private 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 - */ - private static World getWorld(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 - */ - private static String validateRegionId(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}. - * - *

This also validates the region ID.

- * - * @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 - */ - private static ProtectedRegion findExistingRegion(RegionManager regionManager, String id, boolean allowGlobal) throws CommandException { - // Validate the id - validateRegionId(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. - * - *

If the player is standing in several regions, an error will be raised - * and a list of regions will be provided.

- * - * @param regionManager the region manager - * @param player the player - * @return a region - * @throws CommandException thrown if no region was found - */ - private static ProtectedRegion findRegionStandingIn(RegionManager regionManager, Player player) throws CommandException { - return findRegionStandingIn(regionManager, player, false); - } - - /** - * Get the region at the player's location, if possible. - * - *

If the player is standing in several regions, an error will be raised - * and a list of regions will be provided.

- * - *

If the player is not standing in any regions, the global region will - * returned if allowGlobal is true and it exists.

- * - * @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 - */ - private static ProtectedRegion findRegionStandingIn(RegionManager regionManager, Player player, boolean allowGlobal) throws CommandException { - ApplicableRegionSet set = regionManager.getApplicableRegions( - player.getLocation()); - - if (set.size() == 0) { - if (allowGlobal) { - ProtectedRegion global = findExistingRegion(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, and " + - "WorldGuard is not sure what you want.\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 - */ - private static Selection getSelection(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; - } - - /** - * 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 - */ - private static ProtectedRegion createRegionFromSelection(Player player, String id) throws CommandException { - Selection selection = getSelection(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."); - } - } - - /** - * Set a player's selection to a given region. - * - * @param player the player - * @param region the region - * @throws CommandException thrown on a command error - */ - private 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 - */ - private static void setFlag(ProtectedRegion region, Flag flag, CommandSender sender, String value) throws InvalidFlagFormat { - region.setFlag(flag, flag.parseInput(WorldGuardPlugin.inst(), sender, value)); - } - - /** - * Defines a new region. - * - * @param args the arguments - * @param sender the sender - * @throws CommandException any error - */ - @Command(aliases = {"define", "def", "d", "create"}, - usage = " [ [ []]]", - flags = "n", - desc = "Defines a region", - min = 1) - public void define(CommandContext args, CommandSender sender) throws CommandException { - Player player = plugin.checkPlayer(sender); - - // Check permissions - if (!getPermissionModel(sender).mayDefine()) { - throw new CommandPermissionsException(); - } - - // Get and validate the region ID - String id = validateRegionId(args.getString(0), false); - - // Can't replace regions with this command - final RegionManager manager = plugin.getRegionContainer().get(player.getWorld()); - - if (manager != null) { - if (manager.hasRegion(id)) { - throw new CommandException("A region with that ID already exists. To change the shape, use /region redefine " + id); - } - - // Make a region from the user's selection - final ProtectedRegion region = createRegionFromSelection(player, id); - - // Issue a warning about height - 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).)"); - } - - // Hint - 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 " + id + " passthrough allow" + - ChatColor.GRAY + ")"); - } - - RegionAdd task = new RegionAdd(plugin, manager, region); - - // Add the list of region owners - if (args.argsLength() > 1) { - task.setLocatorPolicy(args.hasFlag('n') ? UserLocatorPolicy.NAME_ONLY : UserLocatorPolicy.UUID_ONLY); - task.setOwnersInput(args.getSlice(2)); - } - - ListenableFuture future = plugin.getExecutorService().submit(task); - - AsyncCommandHelper.wrap(future, plugin, player) - .formatUsing(id) - .registerWithSupervisor("Adding the region '%s'...") - .sendMessageAfterDelay("(Please wait... adding '%s'...)") - .thenRespondWith( - "A new region has been made named '%s'.", - "Failed to add the region '%s'"); - } else { - throw new CommandException("Either region support is disabled or region data failed to load in the target world."); - } - } - - /** - * Re-defines a region with a new selection. - * - * @param args the arguments - * @param sender the sender - * @throws CommandException any error - */ - @Command(aliases = {"redefine", "update", "move"}, - usage = "", - desc = "Re-defines the shape of a region", - min = 1, max = 1) - public void redefine(CommandContext args, CommandSender sender) throws CommandException { - Player player = plugin.checkPlayer(sender); - World world = player.getWorld(); - - // Get and validate the region ID - String id = validateRegionId(args.getString(0), false); - - // Lookup the existing region - RegionManager manager = plugin.getRegionContainer().get(world); - - if (manager != null) { - ProtectedRegion existing = findExistingRegion(manager, id, false); - - // Check permissions - if (!getPermissionModel(sender).mayRedefine(existing)) { - throw new CommandPermissionsException(); - } - - // Make a region from the user's selection - ProtectedRegion region = createRegionFromSelection(player, id); - - // Copy details from the old region to the new one - region.setMembers(existing.getMembers()); - region.setOwners(existing.getOwners()); - region.setFlags(existing.getFlags()); - region.setPriority(existing.getPriority()); - try { - region.setParent(existing.getParent()); - } catch (CircularInheritanceException ignore) { - // This should not be thrown - } - - // Issue a warning about height - int height = region.getMaximumPoint().getBlockY() - region.getMinimumPoint().getBlockY(); - if (height <= 2) { - sender.sendMessage(ChatColor.GOLD + - "(Warning: The height of the region was " + (height + 1) + " block(s).)"); - } - - RegionAdd task = new RegionAdd(plugin, manager, region); - - ListenableFuture future = plugin.getExecutorService().submit(task); - - AsyncCommandHelper.wrap(future, plugin, player) - .formatUsing(id) - .registerWithSupervisor("Updating the region '%s'...") - .sendMessageAfterDelay("(Please wait... updating '%s'...)") - .thenRespondWith( - "Region '%s' has been updated with a new area.", - "Failed to update the region '%s'"); - } else { - throw new CommandException("Either region support is disabled or region data failed to load in the target world."); - } - } - - /** - * Claiming command for users. - * - *

This command is a joke and it needs to be rewritten. It was contributed - * code :(

- * - * @param args the arguments - * @param sender the sender - * @throws CommandException any error - */ - @Command(aliases = {"claim"}, - usage = " [ [ []]]", - desc = "Claim a region", - min = 1) - public void claim(CommandContext args, CommandSender sender) throws CommandException { - Player player = plugin.checkPlayer(sender); - LocalPlayer localPlayer = plugin.wrapPlayer(player); - RegionPermissionModel permModel = getPermissionModel(sender); - - // Check permissions - if (!permModel.mayClaim()) { - throw new CommandPermissionsException(); - } - - // Get and validate the region ID - String id = validateRegionId(args.getString(0), false); - - // Can't replace existing regions - RegionManager manager = plugin.getGlobalRegionManager().get(player.getWorld()); - - if (manager != null) { - if (manager.hasRegion(id)) { - throw new CommandException("That region already exists. Please choose a different name."); - } - - // Make a region from the user's selection - ProtectedRegion region = createRegionFromSelection(player, id); - - // Get the list of region owners - /*if (args.argsLength() > 1) { - region.setOwners(RegionDBUtil.parseDomainString(args.getSlice(1), 1)); - }*/ - - WorldConfiguration wcfg = plugin.getGlobalStateManager().get(player.getWorld()); - - // Check whether the player has created too many regions - if (!permModel.mayClaimRegionsUnbounded()) { - int maxRegionCount = wcfg.getMaxRegionCount(player); - if (maxRegionCount >= 0 - && manager.getRegionCountOfPlayer(localPlayer) >= maxRegionCount) { - throw new CommandException( - "You own too many regions, delete one first to claim a new one."); - } - } - - ProtectedRegion existing = manager.getRegion(id); - - // Check for an existing region - if (existing != null) { - if (!existing.getOwners().contains(localPlayer)) { - throw new CommandException( - "This region already exists and you don't own it."); - } - } - - // We have to check whether this region violates the space of any other reion - ApplicableRegionSet regions = manager.getApplicableRegions(region); - - // Check if this region overlaps any other region - if (regions.size() > 0) { - if (!regions.isOwnerOfAll(localPlayer)) { - throw new CommandException("This region overlaps with someone else's region."); - } - } else { - if (wcfg.claimOnlyInsideExistingRegions) { - throw new CommandException("You may only claim regions inside " + - "existing regions that you or your group own."); - } - } - - // Check claim volume - if (!permModel.mayClaimRegionsUnbounded()) { - if (region.volume() > wcfg.maxClaimVolume) { - player.sendMessage(ChatColor.RED + "This region is too large to claim."); - player.sendMessage(ChatColor.RED + - "Max. volume: " + wcfg.maxClaimVolume + ", your volume: " + region.volume()); - return; - } - } - - region.getOwners().addPlayer(player.getName()); - - RegionAdd task = new RegionAdd(plugin, manager, region); - ListenableFuture future = plugin.getExecutorService().submit(task); - - AsyncCommandHelper.wrap(future, plugin, player) - .formatUsing(id) - .registerWithSupervisor("Claiming the region '%s'...") - .sendMessageAfterDelay("(Please wait... claiming '%s'...)") - .thenRespondWith( - "A new region has been claimed named '%s'.", - "Failed to claim the region '%s'"); - } else { - throw new CommandException("Either region support is disabled or region data failed to load in the target world."); - } - } - - /** - * Get a WorldEdit selection from a region. - * - * @param args the arguments - * @param sender the sender - * @throws CommandException any error - */ - @Command(aliases = {"select", "sel", "s"}, - usage = "[id]", - desc = "Load a region as a WorldEdit selection", - min = 0, max = 1) - public void select(CommandContext args, CommandSender sender) throws CommandException { - Player player = plugin.checkPlayer(sender); - World world = player.getWorld(); - RegionManager regionManager = plugin.getGlobalRegionManager().get(world); - ProtectedRegion existing; - - // If no arguments were given, get the region that the player is inside - if (args.argsLength() == 0) { - existing = findRegionStandingIn(regionManager, player); - } else { - existing = findExistingRegion(regionManager, args.getString(0), false); - } - - // Check permissions - if (!getPermissionModel(sender).maySelect(existing)) { - throw new CommandPermissionsException(); - } - - // Select - setPlayerSelection(player, existing); - } - - /** - * Get information about a region. - * - * @param args the arguments - * @param sender the sender - * @throws CommandException any error - */ - @Command(aliases = {"info", "i"}, - usage = "[id]", - flags = "usw:", - desc = "Get information about a region", - min = 0, max = 1) - public void info(CommandContext args, CommandSender sender) throws CommandException { - World world = getWorld(args, sender, 'w'); // Get the world - RegionPermissionModel permModel = getPermissionModel(sender); - - // Lookup the existing region - RegionManager regionManager = plugin.getGlobalRegionManager().get(world); - ProtectedRegion existing; - - if (args.argsLength() == 0) { // Get region from where the player is - if (!(sender instanceof Player)) { - throw new CommandException("Please specify " + - "the region with /region info -w world_name region_name."); - } - - existing = findRegionStandingIn(regionManager, (Player) sender, true); - } else { // Get region from the ID - existing = findExistingRegion(regionManager, args.getString(0), true); - } - - // Check permissions - if (!permModel.mayLookup(existing)) { - throw new CommandPermissionsException(); - } - - // Let the player select the region - if (args.hasFlag('s')) { - // Check permissions - if (!permModel.maySelect(existing)) { - throw new CommandPermissionsException(); - } - - setPlayerSelection(plugin.checkPlayer(sender), existing); - } - - // Print region information - RegionPrintoutBuilder printout = new RegionPrintoutBuilder(existing, args.hasFlag('u') ? null : plugin.getProfileCache()); - ListenableFuture future = Futures.transform( - plugin.getExecutorService().submit(printout), - CommandUtils.messageFunction(sender)); - - // If it takes too long... - FutureProgressListener.addProgressListener( - future, sender, "(Please wait... fetching region information...)"); - - // Send a response message - Futures.addCallback(future, - new MessageFutureCallback.Builder(plugin, sender) - .onFailure("Failed to fetch region information") - .build()); - } - - /** - * List regions. - * - * @param args the arguments - * @param sender the sender - * @throws CommandException any error - */ - @Command(aliases = {"list"}, - usage = "[page]", - desc = "Get a list of regions", - flags = "p:w:", - max = 1) - public void list(CommandContext args, CommandSender sender) throws CommandException { - World world = getWorld(args, sender, 'w'); // Get the world - String ownedBy; - - // Get page - int page = args.getInteger(0, 1) - 1; - if (page < 0) { - page = 0; - } - - // -p flag to lookup a player's regions - if (args.hasFlag('p')) { - ownedBy = args.getFlag('p'); - } else { - ownedBy = null; // List all regions - } - - // Check permissions - if (!getPermissionModel(sender).mayList(ownedBy)) { - ownedBy = sender.getName(); // assume they only want their own - if (!getPermissionModel(sender).mayList(ownedBy)) { - throw new CommandPermissionsException(); - } - } - - RegionManager mgr = plugin.getGlobalRegionManager().get(world); - Map regions = mgr.getRegions(); - - // Build a list of regions to show - List entries = new ArrayList(); - - int index = 0; - for (String id : regions.keySet()) { - RegionListEntry entry = new RegionListEntry(id, index++); - - // Filtering by owner? - if (ownedBy != null) { - entry.isOwner = regions.get(id).isOwner(ownedBy); - entry.isMember = regions.get(id).isMember(ownedBy); - - 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 - + (ownedBy == null ? "Regions (page " : "Regions for " + ownedBy + " (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)); - } - } - } - - /** - * Set a flag. - * - * @param args the arguments - * @param sender the sender - * @throws CommandException any error - */ - @Command(aliases = {"flag", "f"}, - usage = " [-w world] [-g group] [value]", - flags = "g:w:", - desc = "Set flags", - min = 2) - public void flag(CommandContext args, CommandSender sender) throws CommandException { - World world = getWorld(args, sender, 'w'); // Get the world - String flagName = args.getString(1); - String value = args.argsLength() >= 3 ? args.getJoinedStrings(2) : null; - RegionGroup groupValue = null; - RegionPermissionModel permModel = getPermissionModel(sender); - - // Lookup the existing region - RegionManager regionManager = plugin.getGlobalRegionManager().get(world); - ProtectedRegion existing = findExistingRegion(regionManager, - args.getString(0), true); - - // Check permissions - if (!permModel.maySetFlag(existing)) { - throw new CommandPermissionsException(); - } - - Flag foundFlag = DefaultFlag.fuzzyMatchFlag(flagName); - - // We didn't find the flag, so let's print a list of flags that the user - // can use, and do nothing afterwards - if (foundFlag == null) { - StringBuilder list = new StringBuilder(); - - // Need to build a list - for (Flag flag : DefaultFlag.getFlags()) { - // Can the user set this flag? - if (!permModel.maySetFlag(existing, flag)) { - continue; - } - - if (list.length() > 0) { - list.append(", "); - } - - list.append(flag.getName()); - } - - sender.sendMessage(ChatColor.RED + "Unknown flag specified: " + flagName); - sender.sendMessage(ChatColor.RED + "Available " + - "flags: " + list); - - return; - } - - // Also make sure that we can use this flag - // This permission is confusing and probably should be replaced, but - // but not here -- in the model - if (!permModel.maySetFlag(existing, foundFlag)) { - throw new CommandPermissionsException(); - } - - // -g for group flag - if (args.hasFlag('g')) { - String group = args.getFlag('g'); - RegionGroupFlag groupFlag = foundFlag.getRegionGroupFlag(); - - if (groupFlag == null) { - throw new CommandException("Region flag '" + foundFlag.getName() - + "' does not have a group flag!"); - } - - // Parse the [-g group] separately so entire command can abort if parsing - // the [value] part throws an error. - try { - groupValue = groupFlag.parseInput(plugin, sender, group); - } catch (InvalidFlagFormat e) { - throw new CommandException(e.getMessage()); - } - - } - - // Set the flag value if a value was set - if (value != null) { - // Set the flag if [value] was given even if [-g group] was given as well - try { - setFlag(existing, foundFlag, sender, value); - } catch (InvalidFlagFormat e) { - throw new CommandException(e.getMessage()); - } - - sender.sendMessage(ChatColor.YELLOW - + "Region flag " + foundFlag.getName() + " set on '" + - existing.getId() + "' to '" + value + "'."); - - // No value? Clear the flag, if -g isn't specified - } else if (!args.hasFlag('g')) { - // Clear the flag only if neither [value] nor [-g group] was given - existing.setFlag(foundFlag, null); - - // Also clear the associated group flag if one exists - RegionGroupFlag groupFlag = foundFlag.getRegionGroupFlag(); - if (groupFlag != null) { - existing.setFlag(groupFlag, null); - } - - sender.sendMessage(ChatColor.YELLOW - + "Region flag " + foundFlag.getName() + " removed from '" + - existing.getId() + "'. (Any -g(roups) were also removed.)"); - } - - // Now set the group - if (groupValue != null) { - RegionGroupFlag groupFlag = foundFlag.getRegionGroupFlag(); - - // If group set to the default, then clear the group flag - if (groupValue == groupFlag.getDefault()) { - existing.setFlag(groupFlag, null); - sender.sendMessage(ChatColor.YELLOW - + "Region group flag for '" + foundFlag.getName() + "' reset to " + - "default."); - } else { - existing.setFlag(groupFlag, groupValue); - sender.sendMessage(ChatColor.YELLOW - + "Region group flag for '" + foundFlag.getName() + "' set."); - } - } - - // Print region information - RegionPrintoutBuilder printout = new RegionPrintoutBuilder(existing, null); - printout.append(ChatColor.GRAY); - printout.append("(Current flags: "); - printout.appendFlagsList(false); - printout.append(")"); - printout.send(sender); - } - - /** - * Set the priority of a region. - * - * @param args the arguments - * @param sender the sender - * @throws CommandException any error - */ - @Command(aliases = {"setpriority", "priority", "pri"}, - usage = " ", - flags = "w:", - desc = "Set the priority of a region", - min = 2, max = 2) - public void setPriority(CommandContext args, CommandSender sender) - throws CommandException { - World world = getWorld(args, sender, 'w'); // Get the world - int priority = args.getInteger(1); - - // Lookup the existing region - RegionManager regionManager = plugin.getGlobalRegionManager().get(world); - ProtectedRegion existing = findExistingRegion(regionManager, - args.getString(0), false); - - // Check permissions - if (!getPermissionModel(sender).maySetPriority(existing)) { - throw new CommandPermissionsException(); - } - - existing.setPriority(priority); - - sender.sendMessage(ChatColor.YELLOW - + "Priority of '" + existing.getId() + "' set to " - + priority + " (higher numbers override)."); - } - - /** - * Set the parent of a region. - * - * @param args the arguments - * @param sender the sender - * @throws CommandException any error - */ - @Command(aliases = {"setparent", "parent", "par"}, - usage = " [parent-id]", - flags = "w:", - desc = "Set the parent of a region", - min = 1, max = 2) - public void setParent(CommandContext args, CommandSender sender) throws CommandException { - World world = getWorld(args, sender, 'w'); // Get the world - ProtectedRegion parent; - ProtectedRegion child; - - // Lookup the existing region - RegionManager regionManager = plugin.getGlobalRegionManager().get(world); - - // Get parent and child - child = findExistingRegion(regionManager, args.getString(0), false); - if (args.argsLength() == 2) { - parent = findExistingRegion(regionManager, args.getString(1), false); - } else { - parent = null; - } - - // Check permissions - if (!getPermissionModel(sender).maySetParent(child, parent)) { - throw new CommandPermissionsException(); - } - - try { - child.setParent(parent); - } catch (CircularInheritanceException e) { - // Tell the user what's wrong - RegionPrintoutBuilder printout = new RegionPrintoutBuilder(parent, null); - printout.append(ChatColor.RED); - printout.append("Uh oh! Setting '" + parent.getId() + "' to be the parent " + - "of '" + child.getId() + "' would cause circular inheritance.\n"); - printout.append(ChatColor.GRAY); - printout.append("(Current inheritance on '" + parent.getId() + "':\n"); - printout.appendParentTree(true); - printout.append(ChatColor.GRAY); - printout.append(")"); - printout.send(sender); - return; - } - - // Tell the user the current inheritance - RegionPrintoutBuilder printout = new RegionPrintoutBuilder(child, null); - printout.append(ChatColor.YELLOW); - printout.append("Inheritance set for region '" + child.getId() + "'.\n"); - if (parent != null) { - printout.append(ChatColor.GRAY); - printout.append("(Current inheritance:\n"); - printout.appendParentTree(true); - printout.append(ChatColor.GRAY); - printout.append(")"); - } - printout.send(sender); - } - - /** - * Remove a region. - * - * @param args the arguments - * @param sender the sender - * @throws CommandException any error - */ - @Command(aliases = {"remove", "delete", "del", "rem"}, - usage = "", - flags = "w:", - desc = "Remove a region", - min = 1, max = 1) - public void remove(CommandContext args, CommandSender sender) throws CommandException { - World world = getWorld(args, sender, 'w'); // Get the world - - // Lookup the existing region - RegionManager regionManager = plugin.getGlobalRegionManager().get(world); - ProtectedRegion existing = findExistingRegion(regionManager, - args.getString(0), true); - - // Check permissions - if (!getPermissionModel(sender).mayDelete(existing)) { - throw new CommandPermissionsException(); - } - - regionManager.removeRegion(existing.getId()); - - sender.sendMessage(ChatColor.YELLOW + "Region '" + existing.getId() + "' removed."); - } - - /** - * Reload the region database. - * - * @param args the arguments - * @param sender the sender - * @throws CommandException any error - */ - @Command(aliases = {"load", "reload"}, - usage = "[world]", - desc = "Reload regions from file", - flags = "w:") - public void load(CommandContext args, final CommandSender sender) throws CommandException { - World world = null; - try { - world = getWorld(args, sender, 'w'); // Get the world - } catch (CommandException e) { - // assume the user wants to reload all worlds - } - - // Check permissions - if (!getPermissionModel(sender).mayForceLoadRegions()) { - throw new CommandPermissionsException(); - } - - if (world != null) { - RegionManager manager = plugin.getGlobalRegionManager().get(world); - - if (manager == null) { - throw new CommandException("No region manager exists for world '" + world.getName() + "'."); - } - - ListenableFuture future = plugin.getExecutorService().submit(new RegionManagerReload(manager)); - - AsyncCommandHelper.wrap(future, plugin, sender) - .forRegionDataLoad(world, false); - } else { - // Load regions for all worlds - List managers = new ArrayList(); - - for (World w : Bukkit.getServer().getWorlds()) { - RegionManager manager = plugin.getGlobalRegionManager().get(w); - if (manager != null) { - managers.add(manager); - } - } - - ListenableFuture future = plugin.getExecutorService().submit(new RegionManagerReload(managers)); - - AsyncCommandHelper.wrap(future, plugin, sender) - .registerWithSupervisor("Loading regions for all worlds") - .sendMessageAfterDelay("(Please wait... loading region data for all worlds...)") - .thenRespondWith( - "Successfully load the region data for all worlds.", - "Failed to load regions for all worlds"); - } - } - - /** - * Re-save the region database. - * - * @param args the arguments - * @param sender the sender - * @throws CommandException any error - */ - @Command(aliases = {"save", "write"}, - usage = "[world]", - desc = "Re-save regions to file", - flags = "w:") - public void save(CommandContext args, final CommandSender sender) throws CommandException { - World world = null; - try { - world = getWorld(args, sender, 'w'); // Get the world - } catch (CommandException e) { - // assume user wants to save all worlds - } - - // Check permissions - if (!getPermissionModel(sender).mayForceSaveRegions()) { - throw new CommandPermissionsException(); - } - - if (world != null) { - RegionManager manager = plugin.getGlobalRegionManager().get(world); - - if (manager == null) { - throw new CommandException("No region manager exists for world '" + world.getName() + "'."); - } - - ListenableFuture future = plugin.getExecutorService().submit(new RegionmanagerSave(manager)); - - AsyncCommandHelper.wrap(future, plugin, sender) - .forRegionDataSave(world, false); - } else { - // Save for all worlds - List managers = new ArrayList(); - - for (World w : Bukkit.getServer().getWorlds()) { - RegionManager manager = plugin.getGlobalRegionManager().get(w); - if (manager != null) { - managers.add(manager); - } - } - - ListenableFuture future = plugin.getExecutorService().submit(new RegionmanagerSave(managers)); - - AsyncCommandHelper.wrap(future, plugin, sender) - .registerWithSupervisor("Saving regions for all worlds") - .sendMessageAfterDelay("(Please wait... saving region data for all worlds...)") - .thenRespondWith( - "Successfully saved the region data for all worlds.", - "Failed to save regions for all worlds"); - } - } - - /** - * Migrate the region database. - * - * @param args the arguments - * @param sender the sender - * @throws CommandException any error - */ - @Command(aliases = {"migratedb"}, usage = " ", - desc = "Migrate from one Protection Database to another.", min = 2, max = 2) - public void migrateDB(CommandContext args, CommandSender sender) throws CommandException { - // Check permissions - if (!getPermissionModel(sender).mayMigrateRegionStore()) { - throw new CommandPermissionsException(); - } - - /* - String from = args.getString(0).toLowerCase().trim(); - String to = args.getString(1).toLowerCase().trim(); - - if (from.equals(to)) { - throw new CommandException("Will not migrate with common source and target."); - } - - Map> migrators = - AbstractDatabaseMigrator.getMigrators(); - MigratorKey key = new MigratorKey(from,to); - - if (!migrators.containsKey(key)) { - throw new CommandException("No migrator found for that combination and direction."); - } - - long lastRequest = 10000000; - if (this.migrateDBRequestDate != null) { - lastRequest = new Date().getTime() - this.migrateDBRequestDate.getTime(); - } - if (this.migrateDBRequest == null || lastRequest > 60000) { - this.migrateDBRequest = key; - this.migrateDBRequestDate = new Date(); - - throw new CommandException("This command is potentially dangerous.\n" + - "Please ensure you have made a backup of your data, and then re-enter the command exactly to procede."); - } - - Class cls = migrators.get(key); - - try { - AbstractDatabaseMigrator migrator = cls.getConstructor(WorldGuardPlugin.class).newInstance(plugin); - - migrator.migrate(); - } catch (IllegalArgumentException ignore) { - } catch (SecurityException ignore) { - } catch (InstantiationException ignore) { - } catch (IllegalAccessException ignore) { - } catch (InvocationTargetException ignore) { - } catch (NoSuchMethodException ignore) { - } catch (MigrationException e) { - throw new CommandException("Error migrating database: " + e.getMessage()); - } - - sender.sendMessage(ChatColor.YELLOW + "Regions have been migrated successfully.\n" + - "If you wish to use the destination format as your new backend, please update your config and reload WorldGuard."); - */ - } - - /** - * Migrate the region databases to use UUIDs rather than name. - * - * @param args the arguments - * @param sender the sender - * @throws CommandException any error - */ - @Command(aliases = {"migrateuuid"}, - desc = "Migrate loaded databases to use UUIDs", max = 0) - public void migrateUuid(CommandContext args, CommandSender sender) throws CommandException { - // Check permissions - if (!getPermissionModel(sender).mayMigrateRegionNames()) { - throw new CommandPermissionsException(); - } - - LoggerToChatHandler handler = null; - Logger minecraftLogger = null; - - if (sender instanceof Player) { - handler = new LoggerToChatHandler(sender); - handler.setLevel(Level.ALL); - minecraftLogger = Logger.getLogger("Minecraft"); - minecraftLogger.addHandler(handler); - } - - try { - UUIDMigrator migrator = new UUIDMigrator(plugin.getProfileService(), plugin.getLogger()); - migrator.readConfiguration(plugin.getGlobalStateManager()); - List managers = plugin.getGlobalRegionManager().getLoaded(); - - // Try migration - if (migrator.migrate(managers)) { - sender.sendMessage(ChatColor.YELLOW + "Now saving regions... this may take a while."); - - for (RegionManager manager : managers) { - manager.save(); - } - - sender.sendMessage(ChatColor.YELLOW + "Migration complete!"); - } else { - sender.sendMessage(ChatColor.YELLOW + "There were no names to migrate."); - } - } catch (IOException e) { - plugin.getLogger().log(Level.WARNING, "Failed to save", e); - throw new CommandException("Error encountered while saving: " + e.getMessage()); - } catch (MigrationException e) { - plugin.getLogger().log(Level.WARNING, "Failed to migrate", e); - throw new CommandException("Error encountered while migrating: " + e.getMessage()); - } finally { - if (minecraftLogger != null) { - minecraftLogger.removeHandler(handler); - } - } - } - - /** - * Teleport to a region - * - * @param args the arguments - * @param sender the sender - * @throws CommandException any error - */ - @Command(aliases = {"teleport", "tp"}, - usage = "", - flags = "s", - desc = "Teleports you to the location associated with the region.", - min = 1, max = 1) - public void teleport(CommandContext args, CommandSender sender) throws CommandException { - Player player = plugin.checkPlayer(sender); - Location teleportLocation; - - // Lookup the existing region - RegionManager regionManager = plugin.getGlobalRegionManager().get(player.getWorld()); - ProtectedRegion existing = findExistingRegion(regionManager, - args.getString(0), false); - - // Check permissions - if (!getPermissionModel(sender).mayTeleportTo(existing)) { - throw new CommandPermissionsException(); - } - - // -s for spawn location - if (args.hasFlag('s')) { - teleportLocation = existing.getFlag(DefaultFlag.SPAWN_LOC); - - if (teleportLocation == null) { - throw new CommandException( - "The region has no spawn point associated."); - } - } else { - teleportLocation = existing.getFlag(DefaultFlag.TELE_LOC); - - if (teleportLocation == null) { - throw new CommandException( - "The region has no teleport point associated."); - } - } - - player.teleport(BukkitUtil.toLocation(teleportLocation)); - sender.sendMessage("Teleported you to the region '" + existing.getId() + "'."); - } -} +/* + * WorldGuard, a suite of tools for Minecraft + * Copyright (C) sk89q + * 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 . + */ + +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.worldedit.Location; +import com.sk89q.worldedit.bukkit.BukkitUtil; +import com.sk89q.worldguard.LocalPlayer; +import com.sk89q.worldguard.bukkit.WorldConfiguration; +import com.sk89q.worldguard.bukkit.WorldGuardPlugin; +import com.sk89q.worldguard.bukkit.commands.AsyncCommandHelper; +import com.sk89q.worldguard.bukkit.commands.CommandUtils; +import com.sk89q.worldguard.bukkit.commands.FutureProgressListener; +import com.sk89q.worldguard.bukkit.commands.MessageFutureCallback.Builder; +import com.sk89q.worldguard.bukkit.commands.task.RegionAdder; +import com.sk89q.worldguard.bukkit.commands.task.RegionLister; +import com.sk89q.worldguard.bukkit.commands.task.RegionManagerReloader; +import com.sk89q.worldguard.bukkit.commands.task.RegionManagerSaver; +import com.sk89q.worldguard.bukkit.commands.task.RegionRemover; +import com.sk89q.worldguard.bukkit.permission.RegionPermissionModel; +import com.sk89q.worldguard.bukkit.util.LoggerToChatHandler; +import com.sk89q.worldguard.protection.ApplicableRegionSet; +import com.sk89q.worldguard.protection.flags.DefaultFlag; +import com.sk89q.worldguard.protection.flags.Flag; +import com.sk89q.worldguard.protection.flags.InvalidFlagFormat; +import com.sk89q.worldguard.protection.flags.RegionGroup; +import com.sk89q.worldguard.protection.flags.RegionGroupFlag; +import com.sk89q.worldguard.protection.managers.RegionManager; +import com.sk89q.worldguard.protection.regions.ProtectedRegion; +import com.sk89q.worldguard.protection.regions.ProtectedRegion.CircularInheritanceException; +import com.sk89q.worldguard.protection.util.migrator.MigrationException; +import com.sk89q.worldguard.protection.util.migrator.UUIDMigrator; +import org.bukkit.Bukkit; +import org.bukkit.ChatColor; +import org.bukkit.World; +import org.bukkit.command.CommandSender; +import org.bukkit.entity.Player; + +import java.io.IOException; +import java.util.ArrayList; +import java.util.List; +import java.util.logging.Level; +import java.util.logging.Logger; + +import static com.google.common.base.Preconditions.checkNotNull; + +/** + * Implements the /region commands for WorldGuard. + */ +public final class RegionCommands extends RegionCommandsBase { + + private final WorldGuardPlugin plugin; + + public RegionCommands(WorldGuardPlugin plugin) { + checkNotNull(plugin); + this.plugin = plugin; + } + + /** + * Defines a new region. + * + * @param args the arguments + * @param sender the sender + * @throws CommandException any error + */ + @Command(aliases = {"define", "def", "d", "create"}, + usage = " [ [ []]]", + flags = "n", + desc = "Defines a region", + min = 1) + public void define(CommandContext args, CommandSender sender) throws CommandException { + Player player = plugin.checkPlayer(sender); + + // Check permissions + if (!getPermissionModel(sender).mayDefine()) { + throw new CommandPermissionsException(); + } + + String id = checkRegionId(args.getString(0), false); + + RegionManager manager = checkRegionManager(plugin, player.getWorld()); + + checkRegionDoesNotExist(manager, id, true); + + ProtectedRegion region = checkRegionFromSelection(player, id); + warnAboutDimensions(player, region); + informNewUser(player, manager, region); + + RegionAdder task = new RegionAdder(plugin, manager, region); + task.addOwnersFromCommand(args, 2); + ListenableFuture future = plugin.getExecutorService().submit(task); + + AsyncCommandHelper.wrap(future, plugin, player) + .formatUsing(id) + .registerWithSupervisor("Adding the region '%s'...") + .sendMessageAfterDelay("(Please wait... adding '%s'...)") + .thenRespondWith( + "A new region has been made named '%s'.", + "Failed to add the region '%s'"); + } + + /** + * Re-defines a region with a new selection. + * + * @param args the arguments + * @param sender the sender + * @throws CommandException any error + */ + @Command(aliases = {"redefine", "update", "move"}, + usage = "", + desc = "Re-defines the shape of a region", + min = 1, max = 1) + public void redefine(CommandContext args, CommandSender sender) throws CommandException { + Player player = plugin.checkPlayer(sender); + World world = player.getWorld(); + + String id = checkRegionId(args.getString(0), false); + + RegionManager manager = checkRegionManager(plugin, world); + + ProtectedRegion existing = checkExistingRegion(manager, id, false); + + // Check permissions + if (!getPermissionModel(sender).mayRedefine(existing)) { + throw new CommandPermissionsException(); + } + + ProtectedRegion region = checkRegionFromSelection(player, id); + region.copyFrom(existing); + + warnAboutDimensions(sender, region); + + RegionAdder task = new RegionAdder(plugin, manager, region); + ListenableFuture future = plugin.getExecutorService().submit(task); + + AsyncCommandHelper.wrap(future, plugin, player) + .formatUsing(id) + .registerWithSupervisor("Updating the region '%s'...") + .sendMessageAfterDelay("(Please wait... updating '%s'...)") + .thenRespondWith( + "Region '%s' has been updated with a new area.", + "Failed to update the region '%s'"); + } + + /** + * Claiming command for users. + * + *

This command is a joke and it needs to be rewritten. It was contributed + * code :(

+ * + * @param args the arguments + * @param sender the sender + * @throws CommandException any error + */ + @Command(aliases = {"claim"}, + usage = " [ [ []]]", + desc = "Claim a region", + min = 1) + public void claim(CommandContext args, CommandSender sender) throws CommandException { + Player player = plugin.checkPlayer(sender); + LocalPlayer localPlayer = plugin.wrapPlayer(player); + RegionPermissionModel permModel = getPermissionModel(sender); + + // Check permissions + if (!permModel.mayClaim()) { + throw new CommandPermissionsException(); + } + + String id = checkRegionId(args.getString(0), false); + + RegionManager manager = checkRegionManager(plugin, player.getWorld()); + + checkRegionDoesNotExist(manager, id, false); + ProtectedRegion region = checkRegionFromSelection(player, id); + + WorldConfiguration wcfg = plugin.getGlobalStateManager().get(player.getWorld()); + + // Check whether the player has created too many regions + if (!permModel.mayClaimRegionsUnbounded()) { + int maxRegionCount = wcfg.getMaxRegionCount(player); + if (maxRegionCount >= 0 + && manager.getRegionCountOfPlayer(localPlayer) >= maxRegionCount) { + throw new CommandException( + "You own too many regions, delete one first to claim a new one."); + } + } + + ProtectedRegion existing = manager.getRegion(id); + + // Check for an existing region + if (existing != null) { + if (!existing.getOwners().contains(localPlayer)) { + throw new CommandException( + "This region already exists and you don't own it."); + } + } + + // We have to check whether this region violates the space of any other reion + ApplicableRegionSet regions = manager.getApplicableRegions(region); + + // Check if this region overlaps any other region + if (regions.size() > 0) { + if (!regions.isOwnerOfAll(localPlayer)) { + throw new CommandException("This region overlaps with someone else's region."); + } + } else { + if (wcfg.claimOnlyInsideExistingRegions) { + throw new CommandException("You may only claim regions inside " + + "existing regions that you or your group own."); + } + } + + // Check claim volume + if (!permModel.mayClaimRegionsUnbounded()) { + if (region.volume() > wcfg.maxClaimVolume) { + player.sendMessage(ChatColor.RED + "This region is too large to claim."); + player.sendMessage(ChatColor.RED + + "Max. volume: " + wcfg.maxClaimVolume + ", your volume: " + region.volume()); + return; + } + } + + region.getOwners().addPlayer(player.getName()); + + RegionAdder task = new RegionAdder(plugin, manager, region); + ListenableFuture future = plugin.getExecutorService().submit(task); + + AsyncCommandHelper.wrap(future, plugin, player) + .formatUsing(id) + .registerWithSupervisor("Claiming the region '%s'...") + .sendMessageAfterDelay("(Please wait... claiming '%s'...)") + .thenRespondWith( + "A new region has been claimed named '%s'.", + "Failed to claim the region '%s'"); + } + + /** + * Get a WorldEdit selection from a region. + * + * @param args the arguments + * @param sender the sender + * @throws CommandException any error + */ + @Command(aliases = {"select", "sel", "s"}, + usage = "[id]", + desc = "Load a region as a WorldEdit selection", + min = 0, max = 1) + public void select(CommandContext args, CommandSender sender) throws CommandException { + Player player = plugin.checkPlayer(sender); + World world = player.getWorld(); + RegionManager manager = checkRegionManager(plugin, world); + ProtectedRegion existing; + + // If no arguments were given, get the region that the player is inside + if (args.argsLength() == 0) { + existing = checkRegionStandingIn(manager, player); + } else { + existing = checkExistingRegion(manager, args.getString(0), false); + } + + // Check permissions + if (!getPermissionModel(sender).maySelect(existing)) { + throw new CommandPermissionsException(); + } + + // Select + setPlayerSelection(player, existing); + } + + /** + * Get information about a region. + * + * @param args the arguments + * @param sender the sender + * @throws CommandException any error + */ + @Command(aliases = {"info", "i"}, + usage = "[id]", + flags = "usw:", + desc = "Get information about a region", + min = 0, max = 1) + public void info(CommandContext args, CommandSender sender) throws CommandException { + World world = checkWorld(args, sender, 'w'); // Get the world + RegionPermissionModel permModel = getPermissionModel(sender); + + // Lookup the existing region + RegionManager manager = checkRegionManager(plugin, world); + ProtectedRegion existing; + + if (args.argsLength() == 0) { // Get region from where the player is + if (!(sender instanceof Player)) { + throw new CommandException("Please specify " + + "the region with /region info -w world_name region_name."); + } + + existing = checkRegionStandingIn(manager, (Player) sender, true); + } else { // Get region from the ID + existing = checkExistingRegion(manager, args.getString(0), true); + } + + // Check permissions + if (!permModel.mayLookup(existing)) { + throw new CommandPermissionsException(); + } + + // Let the player select the region + if (args.hasFlag('s')) { + // Check permissions + if (!permModel.maySelect(existing)) { + throw new CommandPermissionsException(); + } + + setPlayerSelection(plugin.checkPlayer(sender), existing); + } + + // Print region information + RegionPrintoutBuilder printout = new RegionPrintoutBuilder(existing, args.hasFlag('u') ? null : plugin.getProfileCache()); + ListenableFuture future = Futures.transform( + plugin.getExecutorService().submit(printout), + CommandUtils.messageFunction(sender)); + + // If it takes too long... + FutureProgressListener.addProgressListener( + future, sender, "(Please wait... fetching region information...)"); + + // Send a response message + Futures.addCallback(future, + new Builder(plugin, sender) + .onFailure("Failed to fetch region information") + .build()); + } + + /** + * List regions. + * + * @param args the arguments + * @param sender the sender + * @throws CommandException any error + */ + @Command(aliases = {"list"}, + usage = "[page]", + desc = "Get a list of regions", + flags = "np:w:", + max = 1) + public void list(CommandContext args, CommandSender sender) throws CommandException { + World world = checkWorld(args, sender, 'w'); // Get the world + String ownedBy; + + // Get page + int page = args.getInteger(0, 1) - 1; + if (page < 0) { + page = 0; + } + + // -p flag to lookup a player's regions + if (args.hasFlag('p')) { + ownedBy = args.getFlag('p'); + } else { + ownedBy = null; // List all regions + } + + // Check permissions + if (!getPermissionModel(sender).mayList(ownedBy)) { + ownedBy = sender.getName(); // assume they only want their own + if (!getPermissionModel(sender).mayList(ownedBy)) { + throw new CommandPermissionsException(); + } + } + + RegionManager manager = checkRegionManager(plugin, world); + + RegionLister task = new RegionLister(plugin, manager, sender); + task.setPage(page); + if (ownedBy != null) { + task.filterOwnedByName(ownedBy, args.hasFlag('n')); + } + + ListenableFuture future = plugin.getExecutorService().submit(task); + + AsyncCommandHelper.wrap(future, plugin, sender) + .registerWithSupervisor("Getting list of regions...") + .sendMessageAfterDelay("(Please wait... fetching region list...)") + .thenTellErrorsOnly("Failed to fetch region list"); + } + + /** + * Set a flag. + * + * @param args the arguments + * @param sender the sender + * @throws CommandException any error + */ + @Command(aliases = {"flag", "f"}, + usage = " [-w world] [-g group] [value]", + flags = "g:w:", + desc = "Set flags", + min = 2) + public void flag(CommandContext args, CommandSender sender) throws CommandException { + World world = checkWorld(args, sender, 'w'); // Get the world + String flagName = args.getString(1); + String value = args.argsLength() >= 3 ? args.getJoinedStrings(2) : null; + RegionGroup groupValue = null; + RegionPermissionModel permModel = getPermissionModel(sender); + + // Lookup the existing region + RegionManager manager = checkRegionManager(plugin, world); + ProtectedRegion existing = checkExistingRegion(manager, args.getString(0), true); + + // Check permissions + if (!permModel.maySetFlag(existing)) { + throw new CommandPermissionsException(); + } + + Flag foundFlag = DefaultFlag.fuzzyMatchFlag(flagName); + + // We didn't find the flag, so let's print a list of flags that the user + // can use, and do nothing afterwards + if (foundFlag == null) { + StringBuilder list = new StringBuilder(); + + // Need to build a list + for (Flag flag : DefaultFlag.getFlags()) { + // Can the user set this flag? + if (!permModel.maySetFlag(existing, flag)) { + continue; + } + + if (list.length() > 0) { + list.append(", "); + } + + list.append(flag.getName()); + } + + sender.sendMessage(ChatColor.RED + "Unknown flag specified: " + flagName); + sender.sendMessage(ChatColor.RED + "Available " + + "flags: " + list); + + return; + } + + // Also make sure that we can use this flag + // This permission is confusing and probably should be replaced, but + // but not here -- in the model + if (!permModel.maySetFlag(existing, foundFlag)) { + throw new CommandPermissionsException(); + } + + // -g for group flag + if (args.hasFlag('g')) { + String group = args.getFlag('g'); + RegionGroupFlag groupFlag = foundFlag.getRegionGroupFlag(); + + if (groupFlag == null) { + throw new CommandException("Region flag '" + foundFlag.getName() + + "' does not have a group flag!"); + } + + // Parse the [-g group] separately so entire command can abort if parsing + // the [value] part throws an error. + try { + groupValue = groupFlag.parseInput(plugin, sender, group); + } catch (InvalidFlagFormat e) { + throw new CommandException(e.getMessage()); + } + + } + + // Set the flag value if a value was set + if (value != null) { + // Set the flag if [value] was given even if [-g group] was given as well + try { + setFlag(existing, foundFlag, sender, value); + } catch (InvalidFlagFormat e) { + throw new CommandException(e.getMessage()); + } + + sender.sendMessage(ChatColor.YELLOW + + "Region flag " + foundFlag.getName() + " set on '" + + existing.getId() + "' to '" + value + "'."); + + // No value? Clear the flag, if -g isn't specified + } else if (!args.hasFlag('g')) { + // Clear the flag only if neither [value] nor [-g group] was given + existing.setFlag(foundFlag, null); + + // Also clear the associated group flag if one exists + RegionGroupFlag groupFlag = foundFlag.getRegionGroupFlag(); + if (groupFlag != null) { + existing.setFlag(groupFlag, null); + } + + sender.sendMessage(ChatColor.YELLOW + + "Region flag " + foundFlag.getName() + " removed from '" + + existing.getId() + "'. (Any -g(roups) were also removed.)"); + } + + // Now set the group + if (groupValue != null) { + RegionGroupFlag groupFlag = foundFlag.getRegionGroupFlag(); + + // If group set to the default, then clear the group flag + if (groupValue == groupFlag.getDefault()) { + existing.setFlag(groupFlag, null); + sender.sendMessage(ChatColor.YELLOW + + "Region group flag for '" + foundFlag.getName() + "' reset to " + + "default."); + } else { + existing.setFlag(groupFlag, groupValue); + sender.sendMessage(ChatColor.YELLOW + + "Region group flag for '" + foundFlag.getName() + "' set."); + } + } + + // Print region information + RegionPrintoutBuilder printout = new RegionPrintoutBuilder(existing, null); + printout.append(ChatColor.GRAY); + printout.append("(Current flags: "); + printout.appendFlagsList(false); + printout.append(")"); + printout.send(sender); + } + + /** + * Set the priority of a region. + * + * @param args the arguments + * @param sender the sender + * @throws CommandException any error + */ + @Command(aliases = {"setpriority", "priority", "pri"}, + usage = " ", + flags = "w:", + desc = "Set the priority of a region", + min = 2, max = 2) + public void setPriority(CommandContext args, CommandSender sender) throws CommandException { + World world = checkWorld(args, sender, 'w'); // Get the world + int priority = args.getInteger(1); + + // Lookup the existing region + RegionManager manager = checkRegionManager(plugin, world); + ProtectedRegion existing = checkExistingRegion(manager, args.getString(0), false); + + // Check permissions + if (!getPermissionModel(sender).maySetPriority(existing)) { + throw new CommandPermissionsException(); + } + + existing.setPriority(priority); + + sender.sendMessage(ChatColor.YELLOW + + "Priority of '" + existing.getId() + "' set to " + + priority + " (higher numbers override)."); + } + + /** + * Set the parent of a region. + * + * @param args the arguments + * @param sender the sender + * @throws CommandException any error + */ + @Command(aliases = {"setparent", "parent", "par"}, + usage = " [parent-id]", + flags = "w:", + desc = "Set the parent of a region", + min = 1, max = 2) + public void setParent(CommandContext args, CommandSender sender) throws CommandException { + World world = checkWorld(args, sender, 'w'); // Get the world + ProtectedRegion parent; + ProtectedRegion child; + + // Lookup the existing region + RegionManager manager = checkRegionManager(plugin, world); + + // Get parent and child + child = checkExistingRegion(manager, args.getString(0), false); + if (args.argsLength() == 2) { + parent = checkExistingRegion(manager, args.getString(1), false); + } else { + parent = null; + } + + // Check permissions + if (!getPermissionModel(sender).maySetParent(child, parent)) { + throw new CommandPermissionsException(); + } + + try { + child.setParent(parent); + } catch (CircularInheritanceException e) { + // Tell the user what's wrong + RegionPrintoutBuilder printout = new RegionPrintoutBuilder(parent, null); + printout.append(ChatColor.RED); + assert parent != null; + printout.append("Uh oh! Setting '" + parent.getId() + "' to be the parent " + + "of '" + child.getId() + "' would cause circular inheritance.\n"); + printout.append(ChatColor.GRAY); + printout.append("(Current inheritance on '" + parent.getId() + "':\n"); + printout.appendParentTree(true); + printout.append(ChatColor.GRAY); + printout.append(")"); + printout.send(sender); + return; + } + + // Tell the user the current inheritance + RegionPrintoutBuilder printout = new RegionPrintoutBuilder(child, null); + printout.append(ChatColor.YELLOW); + printout.append("Inheritance set for region '" + child.getId() + "'.\n"); + if (parent != null) { + printout.append(ChatColor.GRAY); + printout.append("(Current inheritance:\n"); + printout.appendParentTree(true); + printout.append(ChatColor.GRAY); + printout.append(")"); + } + printout.send(sender); + } + + /** + * Remove a region. + * + * @param args the arguments + * @param sender the sender + * @throws CommandException any error + */ + @Command(aliases = {"remove", "delete", "del", "rem"}, + usage = "", + flags = "w:", + desc = "Remove a region", + min = 1, max = 1) + public void remove(CommandContext args, CommandSender sender) throws CommandException { + World world = checkWorld(args, sender, 'w'); // Get the world + + // Lookup the existing region + RegionManager manager = checkRegionManager(plugin, world); + ProtectedRegion existing = checkExistingRegion(manager, args.getString(0), true); + + // Check permissions + if (!getPermissionModel(sender).mayDelete(existing)) { + throw new CommandPermissionsException(); + } + + RegionRemover task = new RegionRemover(manager, existing); + + AsyncCommandHelper.wrap(plugin.getExecutorService().submit(task), plugin, sender) + .formatUsing(existing.getId()) + .registerWithSupervisor("Removing the region '%s'...") + .sendMessageAfterDelay("(Please wait... removing '%s'...)") + .thenRespondWith( + "The region named '%s' has been removed.", + "Failed to remove the region '%s'"); + } + + /** + * Reload the region database. + * + * @param args the arguments + * @param sender the sender + * @throws CommandException any error + */ + @Command(aliases = {"load", "reload"}, + usage = "[world]", + desc = "Reload regions from file", + flags = "w:") + public void load(CommandContext args, final CommandSender sender) throws CommandException { + World world = null; + try { + world = checkWorld(args, sender, 'w'); // Get the world + } catch (CommandException e) { + // assume the user wants to reload all worlds + } + + // Check permissions + if (!getPermissionModel(sender).mayForceLoadRegions()) { + throw new CommandPermissionsException(); + } + + if (world != null) { + RegionManager manager = checkRegionManager(plugin, world); + + if (manager == null) { + throw new CommandException("No region manager exists for world '" + world.getName() + "'."); + } + + ListenableFuture future = plugin.getExecutorService().submit(new RegionManagerReloader(manager)); + + AsyncCommandHelper.wrap(future, plugin, sender) + .forRegionDataLoad(world, false); + } else { + // Load regions for all worlds + List managers = new ArrayList(); + + for (World w : Bukkit.getServer().getWorlds()) { + RegionManager manager = plugin.getRegionContainer().get(w); + if (manager != null) { + managers.add(manager); + } + } + + ListenableFuture future = plugin.getExecutorService().submit(new RegionManagerReloader(managers)); + + AsyncCommandHelper.wrap(future, plugin, sender) + .registerWithSupervisor("Loading regions for all worlds") + .sendMessageAfterDelay("(Please wait... loading region data for all worlds...)") + .thenRespondWith( + "Successfully load the region data for all worlds.", + "Failed to load regions for all worlds"); + } + } + + /** + * Re-save the region database. + * + * @param args the arguments + * @param sender the sender + * @throws CommandException any error + */ + @Command(aliases = {"save", "write"}, + usage = "[world]", + desc = "Re-save regions to file", + flags = "w:") + public void save(CommandContext args, final CommandSender sender) throws CommandException { + World world = null; + try { + world = checkWorld(args, sender, 'w'); // Get the world + } catch (CommandException e) { + // assume user wants to save all worlds + } + + // Check permissions + if (!getPermissionModel(sender).mayForceSaveRegions()) { + throw new CommandPermissionsException(); + } + + if (world != null) { + RegionManager manager = checkRegionManager(plugin, world); + + if (manager == null) { + throw new CommandException("No region manager exists for world '" + world.getName() + "'."); + } + + ListenableFuture future = plugin.getExecutorService().submit(new RegionManagerSaver(manager)); + + AsyncCommandHelper.wrap(future, plugin, sender) + .forRegionDataSave(world, false); + } else { + // Save for all worlds + List managers = new ArrayList(); + + for (World w : Bukkit.getServer().getWorlds()) { + RegionManager manager = plugin.getRegionContainer().get(w); + if (manager != null) { + managers.add(manager); + } + } + + ListenableFuture future = plugin.getExecutorService().submit(new RegionManagerSaver(managers)); + + AsyncCommandHelper.wrap(future, plugin, sender) + .registerWithSupervisor("Saving regions for all worlds") + .sendMessageAfterDelay("(Please wait... saving region data for all worlds...)") + .thenRespondWith( + "Successfully saved the region data for all worlds.", + "Failed to save regions for all worlds"); + } + } + + /** + * Migrate the region database. + * + * @param args the arguments + * @param sender the sender + * @throws CommandException any error + */ + @Command(aliases = {"migratedb"}, usage = " ", + desc = "Migrate from one Protection Database to another.", min = 2, max = 2) + public void migrateDB(CommandContext args, CommandSender sender) throws CommandException { + // Check permissions + if (!getPermissionModel(sender).mayMigrateRegionStore()) { + throw new CommandPermissionsException(); + } + + /* + String from = args.getString(0).toLowerCase().trim(); + String to = args.getString(1).toLowerCase().trim(); + + if (from.equals(to)) { + throw new CommandException("Will not migrate with common source and target."); + } + + Map> migrators = + AbstractDatabaseMigrator.getMigrators(); + MigratorKey key = new MigratorKey(from,to); + + if (!migrators.containsKey(key)) { + throw new CommandException("No migrator found for that combination and direction."); + } + + long lastRequest = 10000000; + if (this.migrateDBRequestDate != null) { + lastRequest = new Date().getTime() - this.migrateDBRequestDate.getTime(); + } + if (this.migrateDBRequest == null || lastRequest > 60000) { + this.migrateDBRequest = key; + this.migrateDBRequestDate = new Date(); + + throw new CommandException("This command is potentially dangerous.\n" + + "Please ensure you have made a backup of your data, and then re-enter the command exactly to procede."); + } + + Class cls = migrators.get(key); + + try { + AbstractDatabaseMigrator migrator = cls.getConstructor(WorldGuardPlugin.class).newInstance(plugin); + + migrator.migrate(); + } catch (IllegalArgumentException ignore) { + } catch (SecurityException ignore) { + } catch (InstantiationException ignore) { + } catch (IllegalAccessException ignore) { + } catch (InvocationTargetException ignore) { + } catch (NoSuchMethodException ignore) { + } catch (MigrationException e) { + throw new CommandException("Error migrating database: " + e.getMessage()); + } + + sender.sendMessage(ChatColor.YELLOW + "Regions have been migrated successfully.\n" + + "If you wish to use the destination format as your new backend, please update your config and reload WorldGuard."); + */ + } + + /** + * Migrate the region databases to use UUIDs rather than name. + * + * @param args the arguments + * @param sender the sender + * @throws CommandException any error + */ + @Command(aliases = {"migrateuuid"}, + desc = "Migrate loaded databases to use UUIDs", max = 0) + public void migrateUuid(CommandContext args, CommandSender sender) throws CommandException { + // Check permissions + if (!getPermissionModel(sender).mayMigrateRegionNames()) { + throw new CommandPermissionsException(); + } + + LoggerToChatHandler handler = null; + Logger minecraftLogger = null; + + if (sender instanceof Player) { + handler = new LoggerToChatHandler(sender); + handler.setLevel(Level.ALL); + minecraftLogger = Logger.getLogger("Minecraft"); + minecraftLogger.addHandler(handler); + } + + try { + UUIDMigrator migrator = new UUIDMigrator(plugin.getProfileService(), plugin.getLogger()); + migrator.readConfiguration(plugin.getGlobalStateManager()); + List managers = plugin.getRegionContainer().getLoaded(); + + // Try migration + if (migrator.migrate(managers)) { + sender.sendMessage(ChatColor.YELLOW + "Now saving regions... this may take a while."); + + for (RegionManager manager : managers) { + manager.save(); + } + + sender.sendMessage(ChatColor.YELLOW + "Migration complete!"); + } else { + sender.sendMessage(ChatColor.YELLOW + "There were no names to migrate."); + } + } catch (IOException e) { + plugin.getLogger().log(Level.WARNING, "Failed to save", e); + throw new CommandException("Error encountered while saving: " + e.getMessage()); + } catch (MigrationException e) { + plugin.getLogger().log(Level.WARNING, "Failed to migrate", e); + throw new CommandException("Error encountered while migrating: " + e.getMessage()); + } finally { + if (minecraftLogger != null) { + minecraftLogger.removeHandler(handler); + } + } + } + + /** + * Teleport to a region + * + * @param args the arguments + * @param sender the sender + * @throws CommandException any error + */ + @Command(aliases = {"teleport", "tp"}, + usage = "", + flags = "s", + desc = "Teleports you to the location associated with the region.", + min = 1, max = 1) + public void teleport(CommandContext args, CommandSender sender) throws CommandException { + Player player = plugin.checkPlayer(sender); + Location teleportLocation; + + // Lookup the existing region + RegionManager regionManager = checkRegionManager(plugin, player.getWorld()); + ProtectedRegion existing = checkExistingRegion(regionManager, args.getString(0), false); + + // Check permissions + if (!getPermissionModel(sender).mayTeleportTo(existing)) { + throw new CommandPermissionsException(); + } + + // -s for spawn location + if (args.hasFlag('s')) { + teleportLocation = existing.getFlag(DefaultFlag.SPAWN_LOC); + + if (teleportLocation == null) { + throw new CommandException( + "The region has no spawn point associated."); + } + } else { + teleportLocation = existing.getFlag(DefaultFlag.TELE_LOC); + + if (teleportLocation == null) { + throw new CommandException( + "The region has no teleport point associated."); + } + } + + player.teleport(BukkitUtil.toLocation(teleportLocation)); + sender.sendMessage("Teleported you to the region '" + existing.getId() + "'."); + } +} diff --git a/src/main/java/com/sk89q/worldguard/bukkit/commands/RegionPrintoutBuilder.java b/src/main/java/com/sk89q/worldguard/bukkit/commands/region/RegionPrintoutBuilder.java similarity index 97% rename from src/main/java/com/sk89q/worldguard/bukkit/commands/RegionPrintoutBuilder.java rename to src/main/java/com/sk89q/worldguard/bukkit/commands/region/RegionPrintoutBuilder.java index 97eda335..a03c2745 100644 --- a/src/main/java/com/sk89q/worldguard/bukkit/commands/RegionPrintoutBuilder.java +++ b/src/main/java/com/sk89q/worldguard/bukkit/commands/region/RegionPrintoutBuilder.java @@ -17,7 +17,7 @@ * along with this program. If not, see . */ -package com.sk89q.worldguard.bukkit.commands; +package com.sk89q.worldguard.bukkit.commands.region; import com.sk89q.squirrelid.cache.ProfileCache; import com.sk89q.worldedit.BlockVector; @@ -39,7 +39,7 @@ * Create a region printout, as used in /region info to show information about * a region. */ -class RegionPrintoutBuilder implements Callable { +public class RegionPrintoutBuilder implements Callable { private final ProtectedRegion region; @Nullable @@ -52,7 +52,7 @@ class RegionPrintoutBuilder implements Callable { * @param region the region * @param cache a profile cache, or {@code null} */ - RegionPrintoutBuilder(ProtectedRegion region, @Nullable ProfileCache cache) { + public RegionPrintoutBuilder(ProtectedRegion region, @Nullable ProfileCache cache) { this.region = region; this.cache = cache; } diff --git a/src/main/java/com/sk89q/worldguard/bukkit/commands/task/RegionManagerReload.java b/src/main/java/com/sk89q/worldguard/bukkit/commands/task/RegionManagerReloader.java similarity index 87% rename from src/main/java/com/sk89q/worldguard/bukkit/commands/task/RegionManagerReload.java rename to src/main/java/com/sk89q/worldguard/bukkit/commands/task/RegionManagerReloader.java index 15d3f0a4..372e7dd8 100644 --- a/src/main/java/com/sk89q/worldguard/bukkit/commands/task/RegionManagerReload.java +++ b/src/main/java/com/sk89q/worldguard/bukkit/commands/task/RegionManagerReloader.java @@ -28,16 +28,16 @@ import static com.google.common.base.Preconditions.checkNotNull; -public class RegionManagerReload implements Callable> { +public class RegionManagerReloader implements Callable> { private final Collection managers; - public RegionManagerReload(Collection managers) { + public RegionManagerReloader(Collection managers) { checkNotNull(managers); this.managers = managers; } - public RegionManagerReload(RegionManager... manager) { + public RegionManagerReloader(RegionManager... manager) { this(Arrays.asList(manager)); } diff --git a/src/main/java/com/sk89q/worldguard/bukkit/commands/task/RegionmanagerSave.java b/src/main/java/com/sk89q/worldguard/bukkit/commands/task/RegionManagerSaver.java similarity index 87% rename from src/main/java/com/sk89q/worldguard/bukkit/commands/task/RegionmanagerSave.java rename to src/main/java/com/sk89q/worldguard/bukkit/commands/task/RegionManagerSaver.java index cd6606f5..f55b16e0 100644 --- a/src/main/java/com/sk89q/worldguard/bukkit/commands/task/RegionmanagerSave.java +++ b/src/main/java/com/sk89q/worldguard/bukkit/commands/task/RegionManagerSaver.java @@ -28,16 +28,16 @@ import static com.google.common.base.Preconditions.checkNotNull; -public class RegionmanagerSave implements Callable> { +public class RegionManagerSaver implements Callable> { private final Collection managers; - public RegionmanagerSave(Collection managers) { + public RegionManagerSaver(Collection managers) { checkNotNull(managers); this.managers = managers; } - public RegionmanagerSave(RegionManager... manager) { + public RegionManagerSaver(RegionManager... manager) { this(Arrays.asList(manager)); } diff --git a/src/main/java/com/sk89q/worldguard/bukkit/permission/RegionPermissionModel.java b/src/main/java/com/sk89q/worldguard/bukkit/permission/RegionPermissionModel.java index 3807468b..16570f43 100644 --- a/src/main/java/com/sk89q/worldguard/bukkit/permission/RegionPermissionModel.java +++ b/src/main/java/com/sk89q/worldguard/bukkit/permission/RegionPermissionModel.java @@ -123,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