mirror of
https://github.com/EngineHub/WorldGuard.git
synced 2024-09-28 22:57:29 +02:00
Add task management and improve threaded code.
This commit is contained in:
parent
32e39f5c7c
commit
471b4496c9
@ -30,6 +30,9 @@
|
||||
import com.sk89q.minecraft.util.commands.SimpleInjector;
|
||||
import com.sk89q.minecraft.util.commands.WrappedCommandException;
|
||||
import com.sk89q.odeum.concurrency.EvenMoreExecutors;
|
||||
import com.sk89q.odeum.task.SimpleSupervisor;
|
||||
import com.sk89q.odeum.task.Supervisor;
|
||||
import com.sk89q.odeum.task.Task;
|
||||
import com.sk89q.squirrelid.cache.HashMapCache;
|
||||
import com.sk89q.squirrelid.cache.ProfileCache;
|
||||
import com.sk89q.squirrelid.cache.SQLiteCache;
|
||||
@ -49,6 +52,7 @@
|
||||
import com.sk89q.worldguard.internal.listener.ChestProtectionListener;
|
||||
import com.sk89q.worldguard.internal.listener.RegionProtectionListener;
|
||||
import com.sk89q.worldguard.protection.GlobalRegionManager;
|
||||
import com.sk89q.worldguard.protection.databases.util.UnresolvedNamesException;
|
||||
import com.sk89q.worldguard.protection.managers.RegionManager;
|
||||
import com.sk89q.worldguard.util.FatalConfigurationLoadingException;
|
||||
import org.bukkit.ChatColor;
|
||||
@ -64,6 +68,7 @@
|
||||
import org.bukkit.plugin.Plugin;
|
||||
import org.bukkit.plugin.java.JavaPlugin;
|
||||
|
||||
import javax.annotation.Nullable;
|
||||
import java.io.File;
|
||||
import java.io.FileNotFoundException;
|
||||
import java.io.FileOutputStream;
|
||||
@ -74,6 +79,9 @@
|
||||
import java.util.Iterator;
|
||||
import java.util.List;
|
||||
import java.util.Set;
|
||||
import java.util.concurrent.CancellationException;
|
||||
import java.util.concurrent.RejectedExecutionException;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
import java.util.jar.JarFile;
|
||||
import java.util.logging.Level;
|
||||
import java.util.zip.ZipEntry;
|
||||
@ -88,8 +96,8 @@ public class WorldGuardPlugin extends JavaPlugin {
|
||||
private final GlobalRegionManager globalRegionManager;
|
||||
private final ConfigurationManager configuration;
|
||||
private FlagStateManager flagStateManager;
|
||||
private final ListeningExecutorService executorService = MoreExecutors.listeningDecorator(
|
||||
EvenMoreExecutors.newBoundedCachedThreadPool(0, 4, 20));
|
||||
private final Supervisor supervisor = new SimpleSupervisor();
|
||||
private ListeningExecutorService executorService;
|
||||
private ProfileService profileService;
|
||||
private ProfileCache profileCache;
|
||||
|
||||
@ -124,6 +132,7 @@ public static WorldGuardPlugin inst() {
|
||||
@Override
|
||||
@SuppressWarnings("deprecation")
|
||||
public void onEnable() {
|
||||
executorService = MoreExecutors.listeningDecorator(EvenMoreExecutors.newBoundedCachedThreadPool(0, 1, 20));
|
||||
|
||||
// Set the proper command injector
|
||||
commands.setInjector(new SimpleInjector(this));
|
||||
@ -226,14 +235,33 @@ public void run() {
|
||||
|
||||
@Override
|
||||
public void onDisable() {
|
||||
executorService.shutdownNow();
|
||||
|
||||
try {
|
||||
getLogger().log(Level.INFO, "Shutting down executor and waiting for any pending tasks...");
|
||||
|
||||
List<Task<?>> tasks = supervisor.getTasks();
|
||||
if (!tasks.isEmpty()) {
|
||||
StringBuilder builder = new StringBuilder("Known tasks:");
|
||||
for (Task<?> task : tasks) {
|
||||
builder.append("\n");
|
||||
builder.append(task.getName());
|
||||
}
|
||||
getLogger().log(Level.INFO, builder.toString());
|
||||
}
|
||||
|
||||
executorService.awaitTermination(Integer.MAX_VALUE, TimeUnit.DAYS);
|
||||
} catch (InterruptedException e) {
|
||||
Thread.currentThread().interrupt();
|
||||
}
|
||||
|
||||
globalRegionManager.unload();
|
||||
configuration.unload();
|
||||
this.getServer().getScheduler().cancelTasks(this);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean onCommand(CommandSender sender, Command cmd, String label,
|
||||
String[] args) {
|
||||
public boolean onCommand(CommandSender sender, Command cmd, String label, String[] args) {
|
||||
try {
|
||||
commands.execute(cmd.getName(), args, sender, sender);
|
||||
} catch (CommandPermissionsException e) {
|
||||
@ -244,12 +272,7 @@ public boolean onCommand(CommandSender sender, Command cmd, String label,
|
||||
sender.sendMessage(ChatColor.RED + e.getMessage());
|
||||
sender.sendMessage(ChatColor.RED + e.getUsage());
|
||||
} catch (WrappedCommandException e) {
|
||||
if (e.getCause() instanceof NumberFormatException) {
|
||||
sender.sendMessage(ChatColor.RED + "Number expected, string received instead.");
|
||||
} else {
|
||||
sender.sendMessage(ChatColor.RED + "An error has occurred. See console.");
|
||||
e.printStackTrace();
|
||||
}
|
||||
sender.sendMessage(ChatColor.RED + convertThrowable(e.getCause()));
|
||||
} catch (CommandException e) {
|
||||
sender.sendMessage(ChatColor.RED + e.getMessage());
|
||||
}
|
||||
@ -257,6 +280,31 @@ public boolean onCommand(CommandSender sender, Command cmd, String label,
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Convert the throwable into a somewhat friendly message.
|
||||
*
|
||||
* @param throwable the throwable
|
||||
* @return a message
|
||||
*/
|
||||
public String convertThrowable(@Nullable Throwable throwable) {
|
||||
if (throwable instanceof NumberFormatException) {
|
||||
return "Number expected, string received instead.";
|
||||
} else if (throwable instanceof RejectedExecutionException) {
|
||||
return "There are currently too many tasks queued to add yours. Use /wg running to list queued and running tasks.";
|
||||
} else if (throwable instanceof CancellationException) {
|
||||
return "Task was cancelled";
|
||||
} else if (throwable instanceof InterruptedException) {
|
||||
return "Task was interrupted";
|
||||
} else if (throwable instanceof UnresolvedNamesException) {
|
||||
return throwable.getMessage();
|
||||
} else if (throwable instanceof Exception) {
|
||||
getLogger().log(Level.WARNING, "WorldGuard encountered an unexpected error", throwable);
|
||||
return "Unexpected error occurred: " + ((Exception) throwable).getMessage();
|
||||
} else {
|
||||
return "Unknown error";
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the GlobalRegionManager.
|
||||
*
|
||||
@ -295,6 +343,15 @@ public ConfigurationManager getGlobalStateManager() {
|
||||
return configuration;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the supervisor.
|
||||
*
|
||||
* @return the supervisor
|
||||
*/
|
||||
public Supervisor getSupervisor() {
|
||||
return supervisor;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the global executor service for internal usage (please use your
|
||||
* own executor service).
|
||||
|
@ -0,0 +1,147 @@
|
||||
/*
|
||||
* WorldGuard, a suite of tools for Minecraft
|
||||
* Copyright (C) sk89q <http://www.sk89q.com>
|
||||
* Copyright (C) WorldGuard team and contributors
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify it
|
||||
* under the terms of the GNU Lesser General Public License as published by the
|
||||
* Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License
|
||||
* for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
package com.sk89q.worldguard.bukkit.commands;
|
||||
|
||||
import com.google.common.util.concurrent.Futures;
|
||||
import com.google.common.util.concurrent.ListenableFuture;
|
||||
import com.sk89q.odeum.task.FutureForwardingTask;
|
||||
import com.sk89q.worldguard.bukkit.WorldGuardPlugin;
|
||||
import com.sk89q.worldguard.protection.managers.RegionManager;
|
||||
import org.bukkit.World;
|
||||
import org.bukkit.command.CommandSender;
|
||||
|
||||
import javax.annotation.Nullable;
|
||||
|
||||
import static com.google.common.base.Preconditions.checkNotNull;
|
||||
|
||||
class AsyncCommandHelper {
|
||||
|
||||
private final ListenableFuture<?> future;
|
||||
private final WorldGuardPlugin plugin;
|
||||
private final CommandSender sender;
|
||||
@Nullable
|
||||
private Object[] formatArgs;
|
||||
|
||||
private AsyncCommandHelper(ListenableFuture<?> future, WorldGuardPlugin plugin, CommandSender sender) {
|
||||
checkNotNull(future);
|
||||
checkNotNull(plugin);
|
||||
checkNotNull(sender);
|
||||
|
||||
this.future = future;
|
||||
this.plugin = plugin;
|
||||
this.sender = sender;
|
||||
}
|
||||
|
||||
public AsyncCommandHelper formatUsing(Object... args) {
|
||||
this.formatArgs = args;
|
||||
return this;
|
||||
}
|
||||
|
||||
private String format(String message) {
|
||||
if (formatArgs != null) {
|
||||
return String.format(message, formatArgs);
|
||||
} else {
|
||||
return message;
|
||||
}
|
||||
}
|
||||
|
||||
public AsyncCommandHelper registerWithSupervisor(String description) {
|
||||
plugin.getSupervisor().monitor(
|
||||
FutureForwardingTask.create(
|
||||
future, format(description), sender));
|
||||
return this;
|
||||
}
|
||||
|
||||
public AsyncCommandHelper sendMessageAfterDelay(String message) {
|
||||
FutureProgressListener.addProgressListener(future, sender, format(message));
|
||||
return this;
|
||||
}
|
||||
|
||||
public AsyncCommandHelper thenRespondWith(String success, String failure) {
|
||||
// Send a response message
|
||||
Futures.addCallback(
|
||||
future,
|
||||
new MessageFutureCallback.Builder(plugin, sender)
|
||||
.onSuccess(format(success))
|
||||
.onFailure(format(failure))
|
||||
.build());
|
||||
return this;
|
||||
}
|
||||
|
||||
public AsyncCommandHelper thenTellErrorsOnly(String failure) {
|
||||
// Send a response message
|
||||
Futures.addCallback(
|
||||
future,
|
||||
new MessageFutureCallback.Builder(plugin, sender)
|
||||
.onFailure(format(failure))
|
||||
.build());
|
||||
return this;
|
||||
}
|
||||
|
||||
public AsyncCommandHelper forRegionDataLoad(World world, boolean silent) {
|
||||
checkNotNull(world);
|
||||
|
||||
formatUsing(world.getName());
|
||||
registerWithSupervisor("Loading region data for '%s'");
|
||||
if (silent) {
|
||||
thenTellErrorsOnly("Failed to load regions '%s'");
|
||||
} else {
|
||||
sendMessageAfterDelay("(Please wait... loading the region data for '%s')");
|
||||
thenRespondWith(
|
||||
"Loaded region data for '%s'",
|
||||
"Failed to load regions '%s'");
|
||||
}
|
||||
|
||||
return this;
|
||||
}
|
||||
|
||||
public AsyncCommandHelper forRegionDataSave(World world, boolean silent) {
|
||||
checkNotNull(world);
|
||||
|
||||
formatUsing(world.getName());
|
||||
registerWithSupervisor("Saving region data for '%s'");
|
||||
if (silent) {
|
||||
thenTellErrorsOnly("Failed to save regions '%s'");
|
||||
} else {
|
||||
sendMessageAfterDelay("(Please wait... saving the region data for '%s')");
|
||||
thenRespondWith(
|
||||
"Saved region data for '%s'",
|
||||
"Failed to load regions '%s'");
|
||||
}
|
||||
|
||||
return this;
|
||||
}
|
||||
|
||||
public AsyncCommandHelper thenSaveRegionData(RegionManager manager, World world) {
|
||||
checkNotNull(manager);
|
||||
checkNotNull(world);
|
||||
|
||||
ListenableFuture<?> future = manager.save(true);
|
||||
|
||||
AsyncCommandHelper.wrap(future, plugin, sender).forRegionDataSave(world, true);
|
||||
|
||||
return this;
|
||||
}
|
||||
|
||||
public static AsyncCommandHelper wrap(ListenableFuture<?> future, WorldGuardPlugin plugin, CommandSender sender) {
|
||||
return new AsyncCommandHelper(future, plugin, sender);
|
||||
}
|
||||
|
||||
}
|
@ -20,85 +20,39 @@
|
||||
package com.sk89q.worldguard.bukkit.commands;
|
||||
|
||||
import com.google.common.base.Function;
|
||||
import com.google.common.util.concurrent.FutureCallback;
|
||||
import com.google.common.util.concurrent.Futures;
|
||||
import com.google.common.util.concurrent.ListenableFuture;
|
||||
import com.google.common.util.concurrent.MoreExecutors;
|
||||
import com.sk89q.worldguard.protection.databases.util.UnresolvedNamesException;
|
||||
import com.sk89q.worldguard.protection.managers.RegionManager;
|
||||
import org.bukkit.ChatColor;
|
||||
import org.bukkit.World;
|
||||
import org.bukkit.command.BlockCommandSender;
|
||||
import org.bukkit.command.CommandSender;
|
||||
import org.bukkit.command.ConsoleCommandSender;
|
||||
import org.bukkit.entity.Player;
|
||||
|
||||
import javax.annotation.Nullable;
|
||||
import java.util.Timer;
|
||||
import java.util.concurrent.CancellationException;
|
||||
import java.util.logging.Level;
|
||||
import java.util.logging.Logger;
|
||||
|
||||
import static com.google.common.base.Preconditions.checkNotNull;
|
||||
|
||||
/**
|
||||
* Command-related utility methods.
|
||||
*/
|
||||
final class CommandUtils {
|
||||
|
||||
private static final Logger log = Logger.getLogger(CommandUtils.class.getCanonicalName());
|
||||
private static final Timer timer = new Timer();
|
||||
private static final int MESSAGE_DELAY = 1000;
|
||||
|
||||
private CommandUtils() {
|
||||
}
|
||||
|
||||
/**
|
||||
* Add a message that gets shown after a delay if the future has not
|
||||
* completed.
|
||||
* Get the name of the given owner object.
|
||||
*
|
||||
* @param future the future
|
||||
* @param sender the sender to send a message to
|
||||
* @param message the message to send (will be grey)
|
||||
* @param owner the owner object
|
||||
* @return a name
|
||||
*/
|
||||
static void progressCallback(ListenableFuture<?> future, CommandSender sender, String message) {
|
||||
checkNotNull(future);
|
||||
checkNotNull(sender);
|
||||
checkNotNull(message);
|
||||
|
||||
final MessageTimerTask task = new MessageTimerTask(sender, ChatColor.GRAY + message);
|
||||
timer.schedule(task, MESSAGE_DELAY);
|
||||
future.addListener(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
task.cancel();
|
||||
}
|
||||
}, MoreExecutors.sameThreadExecutor());
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a callback to print a message to the user.
|
||||
*
|
||||
* @param sender the sender
|
||||
* @param successMessage a success message or {@code null} to print nothing
|
||||
* @param errorMessage an error message
|
||||
* @param <T> ignored type
|
||||
* @return a callback
|
||||
*/
|
||||
static <T> FutureCallback<T> messageCallback(final CommandSender sender, @Nullable final String successMessage, final String errorMessage) {
|
||||
checkNotNull(sender);
|
||||
checkNotNull(errorMessage);
|
||||
|
||||
return new FutureCallback<T>() {
|
||||
@Override
|
||||
public void onSuccess(@Nullable T o) {
|
||||
if (successMessage != null) {
|
||||
sender.sendMessage(ChatColor.YELLOW + successMessage);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onFailure(@Nullable Throwable throwable) {
|
||||
sender.sendMessage(ChatColor.RED + errorMessage + ": " + convertThrowable(throwable));
|
||||
}
|
||||
};
|
||||
static String getOwnerName(@Nullable Object owner) {
|
||||
if (owner == null) {
|
||||
return "?";
|
||||
} else if (owner instanceof Player) {
|
||||
return ((Player) owner).getName();
|
||||
} else if (owner instanceof ConsoleCommandSender) {
|
||||
return "*CONSOLE*";
|
||||
} else if (owner instanceof BlockCommandSender) {
|
||||
return ((BlockCommandSender) owner).getBlock().getLocation().toString();
|
||||
} else {
|
||||
return "?";
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
@ -118,71 +72,4 @@ public Object apply(@Nullable String s) {
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
* Return a function to add a prefix and suffix to the input string.
|
||||
*
|
||||
* @param prefix the prefix
|
||||
* @param suffix the suffix
|
||||
* @return a function
|
||||
*/
|
||||
static Function<String, String> messageAppender(final String prefix, final String suffix) {
|
||||
return new Function<String, String>() {
|
||||
@Override
|
||||
public String apply(@Nullable String s) {
|
||||
return prefix + s + suffix;
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a callback to save a region manager on success.
|
||||
*
|
||||
* @param sender the sender
|
||||
* @param manager the region manager
|
||||
* @param world the world
|
||||
* @param silent true to not print a success message
|
||||
* @param <T> an ignored type
|
||||
* @return a callback
|
||||
*/
|
||||
static <T> FutureCallback<T> saveRegionsCallback(final CommandSender sender, final RegionManager manager, final World world, final boolean silent) {
|
||||
checkNotNull(sender);
|
||||
checkNotNull(manager);
|
||||
checkNotNull(world);
|
||||
|
||||
return new FutureCallback<T>() {
|
||||
@Override
|
||||
public void onSuccess(@Nullable T o) {
|
||||
ListenableFuture<?> future = manager.save(true);
|
||||
String successMessage = silent ? null : "Successfully saved the region data for '" + world.getName() + "'.";
|
||||
String failureMessage = "Failed to save the region data for '" + world.getName() + "'";
|
||||
Futures.addCallback(future, messageCallback(sender, successMessage, failureMessage));
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onFailure(@Nullable Throwable throwable) {
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
* Convert the throwable into a somewhat friendly message.
|
||||
*
|
||||
* @param throwable the throwable
|
||||
* @return a message
|
||||
*/
|
||||
private static String convertThrowable(@Nullable Throwable throwable) {
|
||||
if (throwable instanceof CancellationException) {
|
||||
return "Task was cancelled";
|
||||
} else if (throwable instanceof InterruptedException) {
|
||||
return "Task was interrupted";
|
||||
} else if (throwable instanceof UnresolvedNamesException) {
|
||||
return throwable.getMessage();
|
||||
} else if (throwable instanceof Exception) {
|
||||
log.log(Level.WARNING, "WorldGuard encountered an unexpected error", throwable);
|
||||
return "Unexpected error occurred: " + ((Exception) throwable).getMessage();
|
||||
} else {
|
||||
return "Unknown error";
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -0,0 +1,55 @@
|
||||
/*
|
||||
* WorldGuard, a suite of tools for Minecraft
|
||||
* Copyright (C) sk89q <http://www.sk89q.com>
|
||||
* Copyright (C) WorldGuard team and contributors
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify it
|
||||
* under the terms of the GNU Lesser General Public License as published by the
|
||||
* Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License
|
||||
* for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
package com.sk89q.worldguard.bukkit.commands;
|
||||
|
||||
import com.google.common.util.concurrent.ListenableFuture;
|
||||
import com.google.common.util.concurrent.MoreExecutors;
|
||||
import org.bukkit.ChatColor;
|
||||
import org.bukkit.command.CommandSender;
|
||||
|
||||
import java.util.Timer;
|
||||
|
||||
import static com.google.common.base.Preconditions.checkNotNull;
|
||||
|
||||
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) {
|
||||
checkNotNull(sender);
|
||||
checkNotNull(message);
|
||||
|
||||
task = new MessageTimerTask(sender, ChatColor.GRAY + message);
|
||||
timer.schedule(task, MESSAGE_DELAY);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void run() {
|
||||
task.cancel();
|
||||
}
|
||||
|
||||
public static void addProgressListener(ListenableFuture<?> future, CommandSender sender, String message) {
|
||||
future.addListener(new FutureProgressListener(sender, message), MoreExecutors.sameThreadExecutor());
|
||||
}
|
||||
|
||||
}
|
@ -0,0 +1,103 @@
|
||||
/*
|
||||
* WorldGuard, a suite of tools for Minecraft
|
||||
* Copyright (C) sk89q <http://www.sk89q.com>
|
||||
* Copyright (C) WorldGuard team and contributors
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify it
|
||||
* under the terms of the GNU Lesser General Public License as published by the
|
||||
* Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License
|
||||
* for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
package com.sk89q.worldguard.bukkit.commands;
|
||||
|
||||
import com.google.common.util.concurrent.FutureCallback;
|
||||
import com.sk89q.worldguard.bukkit.WorldGuardPlugin;
|
||||
import org.bukkit.ChatColor;
|
||||
import org.bukkit.command.CommandSender;
|
||||
|
||||
import javax.annotation.Nullable;
|
||||
|
||||
import static com.google.common.base.Preconditions.checkNotNull;
|
||||
|
||||
class MessageFutureCallback<V> implements FutureCallback<V> {
|
||||
|
||||
private final WorldGuardPlugin plugin;
|
||||
private final CommandSender sender;
|
||||
@Nullable
|
||||
private final String success;
|
||||
@Nullable
|
||||
private final String failure;
|
||||
|
||||
private MessageFutureCallback(WorldGuardPlugin plugin, CommandSender sender, @Nullable String success, @Nullable String failure) {
|
||||
this.plugin = plugin;
|
||||
this.sender = sender;
|
||||
this.success = success;
|
||||
this.failure = failure;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onSuccess(@Nullable V v) {
|
||||
if (success != null) {
|
||||
sender.sendMessage(ChatColor.YELLOW + success);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onFailure(@Nullable Throwable throwable) {
|
||||
String failure = this.failure != null ? this.failure : "An error occurred";
|
||||
sender.sendMessage(ChatColor.RED + failure + ": " + plugin.convertThrowable(throwable));
|
||||
}
|
||||
|
||||
static class Builder {
|
||||
private final WorldGuardPlugin plugin;
|
||||
private final CommandSender sender;
|
||||
@Nullable
|
||||
private String success;
|
||||
@Nullable
|
||||
private String failure;
|
||||
|
||||
Builder(WorldGuardPlugin plugin, CommandSender sender) {
|
||||
checkNotNull(plugin);
|
||||
checkNotNull(sender);
|
||||
|
||||
this.plugin = plugin;
|
||||
this.sender = sender;
|
||||
}
|
||||
|
||||
public Builder onSuccess(@Nullable String message) {
|
||||
this.success = message;
|
||||
return this;
|
||||
}
|
||||
|
||||
public Builder onFailure(@Nullable String message) {
|
||||
this.failure = message;
|
||||
return this;
|
||||
}
|
||||
|
||||
public <V> MessageFutureCallback<V> build() {
|
||||
return new MessageFutureCallback<V>(plugin, sender, success, failure);
|
||||
}
|
||||
}
|
||||
|
||||
public static <V> MessageFutureCallback<V> createRegionLoadCallback(WorldGuardPlugin plugin, CommandSender sender) {
|
||||
return new Builder(plugin, sender)
|
||||
.onSuccess("Successfully load the region data.")
|
||||
.build();
|
||||
}
|
||||
|
||||
public static <V> MessageFutureCallback<V> createRegionSaveCallback(WorldGuardPlugin plugin, CommandSender sender) {
|
||||
return new Builder(plugin, sender)
|
||||
.onSuccess("Successfully saved the region data.")
|
||||
.build();
|
||||
}
|
||||
|
||||
}
|
@ -19,7 +19,6 @@
|
||||
|
||||
package com.sk89q.worldguard.bukkit.commands;
|
||||
|
||||
import com.google.common.util.concurrent.FutureCallback;
|
||||
import com.google.common.util.concurrent.Futures;
|
||||
import com.google.common.util.concurrent.ListenableFuture;
|
||||
import com.sk89q.minecraft.util.commands.Command;
|
||||
@ -40,9 +39,9 @@
|
||||
import com.sk89q.worldguard.bukkit.WorldGuardPlugin;
|
||||
import com.sk89q.worldguard.protection.ApplicableRegionSet;
|
||||
import com.sk89q.worldguard.protection.databases.RegionDBUtil;
|
||||
import com.sk89q.worldguard.protection.databases.migrators.AbstractDatabaseMigrator;
|
||||
import com.sk89q.worldguard.protection.databases.migrators.MigrationException;
|
||||
import com.sk89q.worldguard.protection.databases.migrators.MigratorKey;
|
||||
import com.sk89q.worldguard.protection.databases.migrator.AbstractDatabaseMigrator;
|
||||
import com.sk89q.worldguard.protection.databases.migrator.MigrationException;
|
||||
import com.sk89q.worldguard.protection.databases.migrator.MigratorKey;
|
||||
import com.sk89q.worldguard.protection.flags.DefaultFlag;
|
||||
import com.sk89q.worldguard.protection.flags.Flag;
|
||||
import com.sk89q.worldguard.protection.flags.InvalidFlagFormat;
|
||||
@ -54,6 +53,7 @@
|
||||
import com.sk89q.worldguard.protection.regions.ProtectedPolygonalRegion;
|
||||
import com.sk89q.worldguard.protection.regions.ProtectedRegion;
|
||||
import com.sk89q.worldguard.protection.regions.ProtectedRegion.CircularInheritanceException;
|
||||
import org.bukkit.Bukkit;
|
||||
import org.bukkit.ChatColor;
|
||||
import org.bukkit.World;
|
||||
import org.bukkit.command.CommandSender;
|
||||
@ -65,8 +65,6 @@
|
||||
import java.util.Date;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.concurrent.RejectedExecutionException;
|
||||
import java.util.logging.Level;
|
||||
|
||||
/**
|
||||
* Implements the /region commands for WorldGuard.
|
||||
@ -91,7 +89,18 @@ public RegionCommands(WorldGuardPlugin plugin) {
|
||||
private static RegionPermissionModel getPermissionModel(CommandSender sender) {
|
||||
return new RegionPermissionModel(WorldGuardPlugin.inst(), sender);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Save the regions asynchronously and alert the sender if any errors
|
||||
* occur during save.
|
||||
*
|
||||
* @param manager the manager to save
|
||||
* @param sender the sender
|
||||
*/
|
||||
private void saveRegionsSilently(RegionManager manager, World world, CommandSender sender) {
|
||||
AsyncCommandHelper.wrap(Futures.immediateFuture(null), plugin, sender).thenSaveRegionData(manager, world);
|
||||
}
|
||||
|
||||
/**
|
||||
* 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.
|
||||
@ -102,8 +111,7 @@ private static RegionPermissionModel getPermissionModel(CommandSender sender) {
|
||||
* @return a world
|
||||
* @throws CommandException on error
|
||||
*/
|
||||
private static World getWorld(CommandContext args, CommandSender sender, char flag)
|
||||
throws CommandException {
|
||||
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 {
|
||||
@ -150,9 +158,7 @@ private static String validateRegionId(String id, boolean allowGlobal)
|
||||
* @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 {
|
||||
private static ProtectedRegion findExistingRegion(RegionManager regionManager, String id, boolean allowGlobal) throws CommandException {
|
||||
// Validate the id
|
||||
validateRegionId(id, allowGlobal);
|
||||
|
||||
@ -186,8 +192,7 @@ private static ProtectedRegion findExistingRegion(
|
||||
* @return a region
|
||||
* @throws CommandException thrown if no region was found
|
||||
*/
|
||||
private static ProtectedRegion findRegionStandingIn(
|
||||
RegionManager regionManager, Player player) throws CommandException {
|
||||
private static ProtectedRegion findRegionStandingIn(RegionManager regionManager, Player player) throws CommandException {
|
||||
return findRegionStandingIn(regionManager, player, false);
|
||||
}
|
||||
|
||||
@ -206,8 +211,7 @@ private static ProtectedRegion findRegionStandingIn(
|
||||
* @return a region
|
||||
* @throws CommandException thrown if no region was found
|
||||
*/
|
||||
private static ProtectedRegion findRegionStandingIn(
|
||||
RegionManager regionManager, Player player, boolean allowGlobal) throws CommandException {
|
||||
private static ProtectedRegion findRegionStandingIn(RegionManager regionManager, Player player, boolean allowGlobal) throws CommandException {
|
||||
ApplicableRegionSet set = regionManager.getApplicableRegions(
|
||||
player.getLocation());
|
||||
|
||||
@ -272,9 +276,7 @@ private static Selection getSelection(Player player) throws CommandException {
|
||||
* @return a new region
|
||||
* @throws CommandException thrown on an error
|
||||
*/
|
||||
private static ProtectedRegion createRegionFromSelection(Player player, String id)
|
||||
throws CommandException {
|
||||
|
||||
private static ProtectedRegion createRegionFromSelection(Player player, String id) throws CommandException {
|
||||
Selection selection = getSelection(player);
|
||||
|
||||
// Detect the type of region from WorldEdit
|
||||
@ -293,84 +295,6 @@ private static ProtectedRegion createRegionFromSelection(Player player, String i
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Save the region database.
|
||||
*
|
||||
* @param sender the sender
|
||||
* @param regionManager the region manager
|
||||
* @param silent whether to suppress messages sent to the player
|
||||
* @throws CommandException throw on an error
|
||||
*/
|
||||
private ListenableFuture<?> commitChanges(final CommandSender sender, RegionManager regionManager, final World world, final boolean silent) throws CommandException {
|
||||
ListenableFuture<?> future;
|
||||
|
||||
try {
|
||||
future = regionManager.save(true);
|
||||
} catch (RejectedExecutionException e) {
|
||||
throw new CommandException("There are too many interleaved load and save tasks currently queued. Please try again later.");
|
||||
}
|
||||
|
||||
if (!silent) {
|
||||
sender.sendMessage(ChatColor.GRAY + "(A save of the region data has been queued.)");
|
||||
}
|
||||
|
||||
Futures.addCallback(future, new FutureCallback<Object>() {
|
||||
@Override
|
||||
public void onSuccess(Object o) {
|
||||
if (!silent) {
|
||||
sender.sendMessage(ChatColor.YELLOW + "Successfully saved the region data for the '" + world.getName() + "' world.");
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onFailure(Throwable throwable) {
|
||||
sender.sendMessage(ChatColor.RED + "Failed to save region data for the '" + world.getName() + "' world: " + throwable.getMessage());
|
||||
plugin.getLogger().log(Level.WARNING, "Failed to save region data", throwable);
|
||||
}
|
||||
});
|
||||
|
||||
return future;
|
||||
}
|
||||
|
||||
/**
|
||||
* Load the region database.
|
||||
*
|
||||
* @param sender the sender
|
||||
* @param regionManager the region manager
|
||||
* @param silent whether to suppress messages sent to the player
|
||||
* @throws CommandException throw on an error
|
||||
*/
|
||||
private ListenableFuture<?> reloadChanges(final CommandSender sender, RegionManager regionManager, final World world, final boolean silent) throws CommandException {
|
||||
ListenableFuture<?> future;
|
||||
|
||||
try {
|
||||
future = regionManager.load(true);
|
||||
} catch (RejectedExecutionException e) {
|
||||
throw new CommandException("There are too many interleaved load and save tasks currently queued. Please try again later.");
|
||||
}
|
||||
|
||||
if (!silent) {
|
||||
sender.sendMessage(ChatColor.GRAY + "(A load of the region data has been queued.)");
|
||||
}
|
||||
|
||||
Futures.addCallback(future, new FutureCallback<Object>() {
|
||||
@Override
|
||||
public void onSuccess(Object o) {
|
||||
if (!silent) {
|
||||
sender.sendMessage(ChatColor.YELLOW + "Successfully loaded the region data for the '" + world.getName() + "' world.");
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onFailure(Throwable throwable) {
|
||||
sender.sendMessage(ChatColor.RED + "Failed to load region data for the '" + world.getName() + "' world: " + throwable.getMessage());
|
||||
plugin.getLogger().log(Level.WARNING, "Failed to load region data", throwable);
|
||||
}
|
||||
});
|
||||
|
||||
return future;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set a player's selection to a given region.
|
||||
*
|
||||
@ -422,9 +346,7 @@ private static void setPlayerSelection(Player player, ProtectedRegion region)
|
||||
* @param value the value
|
||||
* @throws InvalidFlagFormat thrown if the value is invalid
|
||||
*/
|
||||
private static <V> void setFlag(ProtectedRegion region,
|
||||
Flag<V> flag, CommandSender sender, String value)
|
||||
throws InvalidFlagFormat {
|
||||
private static <V> void setFlag(ProtectedRegion region, Flag<V> flag, CommandSender sender, String value) throws InvalidFlagFormat {
|
||||
region.setFlag(flag, flag.parseInput(WorldGuardPlugin.inst(), sender, value));
|
||||
}
|
||||
|
||||
@ -439,8 +361,7 @@ private static <V> void setFlag(ProtectedRegion region,
|
||||
usage = "<id> [<owner1> [<owner2> [<owners...>]]]",
|
||||
desc = "Defines a region",
|
||||
min = 1)
|
||||
public void define(CommandContext args, CommandSender sender)
|
||||
throws CommandException {
|
||||
public void define(CommandContext args, CommandSender sender) throws CommandException {
|
||||
Player player = plugin.checkPlayer(sender);
|
||||
|
||||
// Check permissions
|
||||
@ -466,9 +387,6 @@ public void define(CommandContext args, CommandSender sender)
|
||||
if (args.argsLength() > 1) {
|
||||
region.setOwners(RegionDBUtil.parseDomainString(args.getSlice(1), 1));
|
||||
}
|
||||
|
||||
regionManager.addRegion(region);
|
||||
commitChanges(sender, regionManager, player.getWorld(), true); // Save to disk
|
||||
|
||||
// Issue a warning about height
|
||||
int height = region.getMaximumPoint().getBlockY() - region.getMinimumPoint().getBlockY();
|
||||
@ -488,6 +406,12 @@ public void define(CommandContext args, CommandSender sender)
|
||||
|
||||
// Tell the user
|
||||
sender.sendMessage(ChatColor.YELLOW + "A new region has been made named '" + id + "'.");
|
||||
|
||||
// Add region
|
||||
regionManager.addRegion(region);
|
||||
|
||||
// Save regions
|
||||
saveRegionsSilently(regionManager, player.getWorld(), sender);
|
||||
}
|
||||
|
||||
/**
|
||||
@ -501,8 +425,7 @@ public void define(CommandContext args, CommandSender sender)
|
||||
usage = "<id>",
|
||||
desc = "Re-defines the shape of a region",
|
||||
min = 1, max = 1)
|
||||
public void redefine(CommandContext args, CommandSender sender)
|
||||
throws CommandException {
|
||||
public void redefine(CommandContext args, CommandSender sender) throws CommandException {
|
||||
Player player = plugin.checkPlayer(sender);
|
||||
World world = player.getWorld();
|
||||
|
||||
@ -532,9 +455,6 @@ public void redefine(CommandContext args, CommandSender sender)
|
||||
// This should not be thrown
|
||||
}
|
||||
|
||||
regionManager.addRegion(region); // Replace region
|
||||
commitChanges(sender, regionManager, player.getWorld(), true); // Save to disk
|
||||
|
||||
// Issue a warning about height
|
||||
int height = region.getMaximumPoint().getBlockY() - region.getMinimumPoint().getBlockY();
|
||||
if (height <= 2) {
|
||||
@ -543,6 +463,11 @@ public void redefine(CommandContext args, CommandSender sender)
|
||||
}
|
||||
|
||||
sender.sendMessage(ChatColor.YELLOW + "Region '" + id + "' updated with new area.");
|
||||
|
||||
regionManager.addRegion(region); // Replace region
|
||||
|
||||
// Save regions
|
||||
saveRegionsSilently(regionManager, world, sender);
|
||||
}
|
||||
|
||||
/**
|
||||
@ -573,8 +498,8 @@ public void claim(CommandContext args, CommandSender sender) throws CommandExcep
|
||||
String id = validateRegionId(args.getString(0), false);
|
||||
|
||||
// Can't replace existing regions
|
||||
RegionManager mgr = plugin.getGlobalRegionManager().get(player.getWorld());
|
||||
if (mgr.hasRegion(id)) {
|
||||
RegionManager regionManager = plugin.getGlobalRegionManager().get(player.getWorld());
|
||||
if (regionManager.hasRegion(id)) {
|
||||
throw new CommandException(
|
||||
"That region already exists. Please choose a different name.");
|
||||
}
|
||||
@ -593,13 +518,13 @@ public void claim(CommandContext args, CommandSender sender) throws CommandExcep
|
||||
if (!permModel.mayClaimRegionsUnbounded()) {
|
||||
int maxRegionCount = wcfg.getMaxRegionCount(player);
|
||||
if (maxRegionCount >= 0
|
||||
&& mgr.getRegionCountOfPlayer(localPlayer) >= maxRegionCount) {
|
||||
&& regionManager.getRegionCountOfPlayer(localPlayer) >= maxRegionCount) {
|
||||
throw new CommandException(
|
||||
"You own too many regions, delete one first to claim a new one.");
|
||||
}
|
||||
}
|
||||
|
||||
ProtectedRegion existing = mgr.getRegionExact(id);
|
||||
ProtectedRegion existing = regionManager.getRegionExact(id);
|
||||
|
||||
// Check for an existing region
|
||||
if (existing != null) {
|
||||
@ -610,7 +535,7 @@ public void claim(CommandContext args, CommandSender sender) throws CommandExcep
|
||||
}
|
||||
|
||||
// We have to check whether this region violates the space of any other reion
|
||||
ApplicableRegionSet regions = mgr.getApplicableRegions(region);
|
||||
ApplicableRegionSet regions = regionManager.getApplicableRegions(region);
|
||||
|
||||
// Check if this region overlaps any other region
|
||||
if (regions.size() > 0) {
|
||||
@ -634,34 +559,15 @@ public void claim(CommandContext args, CommandSender sender) throws CommandExcep
|
||||
}
|
||||
}
|
||||
|
||||
/*if (plugin.getGlobalConfiguration().getiConomy() != null && wcfg.useiConomy && wcfg.buyOnClaim) {
|
||||
if (iConomy.getBank().hasAccount(player.getName())) {
|
||||
Account account = iConomy.getBank().getAccount(player.getName());
|
||||
double balance = account.getBalance();
|
||||
double regionCosts = region.countBlocks() * wcfg.buyOnClaimPrice;
|
||||
if (balance >= regionCosts) {
|
||||
account.subtract(regionCosts);
|
||||
player.sendMessage(ChatColor.YELLOW + "You have bought that region for "
|
||||
+ iConomy.getBank().format(regionCosts));
|
||||
account.save();
|
||||
} else {
|
||||
player.sendMessage(ChatColor.RED + "You have not enough money.");
|
||||
player.sendMessage(ChatColor.RED + "The region you want to claim costs "
|
||||
+ iConomy.getBank().format(regionCosts));
|
||||
player.sendMessage(ChatColor.RED + "You have " + iConomy.getBank().format(balance));
|
||||
return;
|
||||
}
|
||||
} else {
|
||||
player.sendMessage(ChatColor.YELLOW + "You have not enough money.");
|
||||
return;
|
||||
}
|
||||
}*/
|
||||
|
||||
region.getOwners().addPlayer(player.getName());
|
||||
|
||||
mgr.addRegion(region);
|
||||
commitChanges(sender, mgr, player.getWorld(), true); // Save to disk
|
||||
|
||||
sender.sendMessage(ChatColor.YELLOW + "Region '" + id + "' updated with new area.");
|
||||
|
||||
// Replace region
|
||||
regionManager.addRegion(region);
|
||||
|
||||
// Save regions
|
||||
saveRegionsSilently(regionManager, player.getWorld(), sender);
|
||||
}
|
||||
|
||||
/**
|
||||
@ -733,22 +639,31 @@ public void info(CommandContext args, CommandSender sender) throws CommandExcept
|
||||
throw new CommandPermissionsException();
|
||||
}
|
||||
|
||||
// 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));
|
||||
Futures.addCallback(future, CommandUtils.messageCallback(sender, null, "Failed to retrieve region info"));
|
||||
|
||||
// Let the player also select the region
|
||||
// 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());
|
||||
}
|
||||
|
||||
/**
|
||||
@ -963,8 +878,6 @@ public void flag(CommandContext args, CommandSender sender) throws CommandExcept
|
||||
}
|
||||
}
|
||||
|
||||
commitChanges(sender, regionManager, world, true); // Save to disk
|
||||
|
||||
// Print region information
|
||||
RegionPrintoutBuilder printout = new RegionPrintoutBuilder(existing, null);
|
||||
printout.append(ChatColor.GRAY);
|
||||
@ -972,6 +885,9 @@ public void flag(CommandContext args, CommandSender sender) throws CommandExcept
|
||||
printout.appendFlagsList(false);
|
||||
printout.append(")");
|
||||
printout.send(sender);
|
||||
|
||||
// Save regions
|
||||
saveRegionsSilently(regionManager, world, sender);
|
||||
}
|
||||
|
||||
/**
|
||||
@ -1002,11 +918,13 @@ public void setPriority(CommandContext args, CommandSender sender)
|
||||
}
|
||||
|
||||
existing.setPriority(priority);
|
||||
commitChanges(sender, regionManager, world, true); // Save to disk
|
||||
|
||||
sender.sendMessage(ChatColor.YELLOW
|
||||
+ "Priority of '" + existing.getId() + "' set to "
|
||||
+ priority + " (higher numbers override).");
|
||||
|
||||
// Save regions
|
||||
saveRegionsSilently(regionManager, world, sender);
|
||||
}
|
||||
|
||||
/**
|
||||
@ -1058,8 +976,6 @@ public void setParent(CommandContext args, CommandSender sender) throws CommandE
|
||||
printout.send(sender);
|
||||
return;
|
||||
}
|
||||
|
||||
commitChanges(sender, regionManager, world, true); // Save to disk
|
||||
|
||||
// Tell the user the current inheritance
|
||||
RegionPrintoutBuilder printout = new RegionPrintoutBuilder(child, null);
|
||||
@ -1073,6 +989,9 @@ public void setParent(CommandContext args, CommandSender sender) throws CommandE
|
||||
printout.append(")");
|
||||
}
|
||||
printout.send(sender);
|
||||
|
||||
// Save regions
|
||||
saveRegionsSilently(regionManager, world, sender);
|
||||
}
|
||||
|
||||
/**
|
||||
@ -1101,10 +1020,11 @@ public void remove(CommandContext args, CommandSender sender) throws CommandExce
|
||||
}
|
||||
|
||||
regionManager.removeRegion(existing.getId());
|
||||
commitChanges(sender, regionManager, world, true); // Save to disk
|
||||
|
||||
sender.sendMessage(ChatColor.YELLOW
|
||||
+ "Region '" + existing.getId() + "' removed.");
|
||||
sender.sendMessage(ChatColor.YELLOW + "Region '" + existing.getId() + "' removed.");
|
||||
|
||||
// Save regions
|
||||
saveRegionsSilently(regionManager, world, sender);
|
||||
}
|
||||
|
||||
/**
|
||||
@ -1132,33 +1052,33 @@ public void load(CommandContext args, final CommandSender sender) throws Command
|
||||
}
|
||||
|
||||
if (world != null) {
|
||||
RegionManager regionManager = plugin.getGlobalRegionManager().get(world);
|
||||
if (regionManager == null) {
|
||||
RegionManager manager = plugin.getGlobalRegionManager().get(world);
|
||||
|
||||
if (manager == null) {
|
||||
throw new CommandException("No region manager exists for world '" + world.getName() + "'.");
|
||||
}
|
||||
reloadChanges(sender, regionManager, world, false);
|
||||
|
||||
ListenableFuture<?> future = manager.load(true);
|
||||
|
||||
AsyncCommandHelper.wrap(future, plugin, sender)
|
||||
.forRegionDataLoad(world, false);
|
||||
} else {
|
||||
// Load regions for all worlds
|
||||
List<ListenableFuture<?>> futures = new ArrayList<ListenableFuture<?>>();
|
||||
for (World w : plugin.getServer().getWorlds()) {
|
||||
RegionManager regionManager = plugin.getGlobalRegionManager().get(w);
|
||||
if (regionManager == null) {
|
||||
continue;
|
||||
for (World w : Bukkit.getServer().getWorlds()) {
|
||||
RegionManager manager = plugin.getGlobalRegionManager().get(w);
|
||||
if (manager != null) {
|
||||
futures.add(manager.load(true));
|
||||
}
|
||||
futures.add(reloadChanges(sender, regionManager, world, true));
|
||||
}
|
||||
ListenableFuture<?> future = Futures.successfulAsList(futures);
|
||||
|
||||
Futures.addCallback(Futures.allAsList(futures), new FutureCallback<Object>() {
|
||||
@Override
|
||||
public void onSuccess(Object o) {
|
||||
sender.sendMessage(ChatColor.YELLOW + "Successfully loaded region data for all worlds.");
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onFailure(Throwable throwable) {
|
||||
sender.sendMessage(ChatColor.RED + "Failed to load region data for all worlds: " + throwable.getMessage());
|
||||
plugin.getLogger().log(Level.WARNING, "Failed to load region data", throwable);
|
||||
}
|
||||
});
|
||||
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");
|
||||
}
|
||||
}
|
||||
|
||||
@ -1187,34 +1107,33 @@ public void save(CommandContext args, final CommandSender sender) throws Command
|
||||
}
|
||||
|
||||
if (world != null) {
|
||||
RegionManager regionManager = plugin.getGlobalRegionManager().get(world);
|
||||
if (regionManager == null) {
|
||||
RegionManager manager = plugin.getGlobalRegionManager().get(world);
|
||||
|
||||
if (manager == null) {
|
||||
throw new CommandException("No region manager exists for world '" + world.getName() + "'.");
|
||||
}
|
||||
commitChanges(sender, regionManager, world, false);
|
||||
|
||||
ListenableFuture<?> future = manager.save(true);
|
||||
|
||||
AsyncCommandHelper.wrap(future, plugin, sender)
|
||||
.forRegionDataSave(world, false);
|
||||
} else {
|
||||
sender.sendMessage(ChatColor.YELLOW + "Saving all region databases... This might take a bit.");
|
||||
// Save for all worlds
|
||||
List<ListenableFuture<?>> futures = new ArrayList<ListenableFuture<?>>();
|
||||
for (World w : plugin.getServer().getWorlds()) {
|
||||
RegionManager regionManager = plugin.getGlobalRegionManager().get(w);
|
||||
if (regionManager == null) {
|
||||
continue;
|
||||
for (World w : Bukkit.getServer().getWorlds()) {
|
||||
RegionManager manager = plugin.getGlobalRegionManager().get(w);
|
||||
if (manager != null) {
|
||||
futures.add(manager.save(true));
|
||||
}
|
||||
futures.add(commitChanges(sender, regionManager, world, true));
|
||||
}
|
||||
ListenableFuture<?> future = Futures.successfulAsList(futures);
|
||||
|
||||
Futures.addCallback(Futures.allAsList(futures), new FutureCallback<Object>() {
|
||||
@Override
|
||||
public void onSuccess(Object o) {
|
||||
sender.sendMessage(ChatColor.YELLOW + "Successfully saved region data for all worlds.");
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onFailure(Throwable throwable) {
|
||||
sender.sendMessage(ChatColor.RED + "Failed to save region data for all worlds: " + throwable.getMessage());
|
||||
plugin.getLogger().log(Level.WARNING, "Failed to save region data", throwable);
|
||||
}
|
||||
});
|
||||
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");
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -36,9 +36,6 @@
|
||||
import org.bukkit.command.CommandSender;
|
||||
import org.bukkit.entity.Player;
|
||||
|
||||
import static com.google.common.util.concurrent.Futures.addCallback;
|
||||
import static com.sk89q.worldguard.bukkit.commands.CommandUtils.*;
|
||||
|
||||
// @TODO: A lot of code duplication here! Need to fix.
|
||||
|
||||
public class RegionMemberCommands {
|
||||
@ -74,8 +71,8 @@ public void addMember(CommandContext args, CommandSender sender) throws CommandE
|
||||
|
||||
String id = args.getString(0);
|
||||
|
||||
RegionManager mgr = plugin.getGlobalRegionManager().get(world);
|
||||
ProtectedRegion region = mgr.getRegion(id);
|
||||
RegionManager manager = plugin.getGlobalRegionManager().get(world);
|
||||
ProtectedRegion region = manager.getRegion(id);
|
||||
|
||||
if (region == null) {
|
||||
throw new CommandException("Could not find a region by that ID.");
|
||||
@ -103,9 +100,12 @@ public void addMember(CommandContext args, CommandSender sender) throws CommandE
|
||||
plugin.getExecutorService().submit(resolver),
|
||||
resolver.createAddAllFunction(region.getMembers()));
|
||||
|
||||
progressCallback(future, sender, "(Please wait... resolving names into UUIDs...)");
|
||||
addCallback(future, messageCallback(sender, "Region '" + id + "' updated.", "Failed to add members"));
|
||||
addCallback(future, saveRegionsCallback(sender, mgr, world, true));
|
||||
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")
|
||||
.thenSaveRegionData(manager, world);
|
||||
}
|
||||
|
||||
@Command(aliases = {"addowner", "addowner", "ao"},
|
||||
@ -133,8 +133,8 @@ public void addOwner(CommandContext args, CommandSender sender) throws CommandEx
|
||||
|
||||
String id = args.getString(0);
|
||||
|
||||
RegionManager mgr = plugin.getGlobalRegionManager().get(world);
|
||||
ProtectedRegion region = mgr.getRegion(id);
|
||||
RegionManager manager = plugin.getGlobalRegionManager().get(world);
|
||||
ProtectedRegion region = manager.getRegion(id);
|
||||
|
||||
if (region == null) {
|
||||
throw new CommandException("Could not find a region by that ID.");
|
||||
@ -148,7 +148,7 @@ public void addOwner(CommandContext args, CommandSender sender) throws CommandEx
|
||||
if (flag != null && flag && owners != null && owners.size() == 0) {
|
||||
if (!plugin.hasPermission(player, "worldguard.region.unlimited")) {
|
||||
int maxRegionCount = plugin.getGlobalStateManager().get(world).getMaxRegionCount(player);
|
||||
if (maxRegionCount >= 0 && mgr.getRegionCountOfPlayer(localPlayer)
|
||||
if (maxRegionCount >= 0 && manager.getRegionCountOfPlayer(localPlayer)
|
||||
>= maxRegionCount) {
|
||||
throw new CommandException("You already own the maximum allowed amount of regions.");
|
||||
}
|
||||
@ -175,9 +175,12 @@ public void addOwner(CommandContext args, CommandSender sender) throws CommandEx
|
||||
plugin.getExecutorService().submit(resolver),
|
||||
resolver.createAddAllFunction(region.getOwners()));
|
||||
|
||||
progressCallback(future, sender, "(Please wait... resolving names into UUIDs...)");
|
||||
addCallback(future, messageCallback(sender, "Region '" + id + "' updated.", "Failed to add owners"));
|
||||
addCallback(future, saveRegionsCallback(sender, mgr, world, true));
|
||||
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")
|
||||
.thenSaveRegionData(manager, world);
|
||||
}
|
||||
|
||||
@Command(aliases = {"removemember", "remmember", "removemem", "remmem", "rm"},
|
||||
@ -205,8 +208,8 @@ public void removeMember(CommandContext args, CommandSender sender) throws Comma
|
||||
|
||||
String id = args.getString(0);
|
||||
|
||||
RegionManager mgr = plugin.getGlobalRegionManager().get(world);
|
||||
ProtectedRegion region = mgr.getRegion(id);
|
||||
RegionManager manager = plugin.getGlobalRegionManager().get(world);
|
||||
ProtectedRegion region = manager.getRegion(id);
|
||||
|
||||
if (region == null) {
|
||||
throw new CommandException("Could not find a region by that ID.");
|
||||
@ -246,9 +249,12 @@ public void removeMember(CommandContext args, CommandSender sender) throws Comma
|
||||
resolver.createRemoveAllFunction(region.getMembers()));
|
||||
}
|
||||
|
||||
progressCallback(future, sender, "(Please wait... resolving names into UUIDs...)");
|
||||
addCallback(future, messageCallback(sender, "Region '" + id + "' updated.", "Failed to remove members"));
|
||||
addCallback(future, saveRegionsCallback(sender, mgr, world, true));
|
||||
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")
|
||||
.thenSaveRegionData(manager, world);
|
||||
}
|
||||
|
||||
@Command(aliases = {"removeowner", "remowner", "ro"},
|
||||
@ -277,8 +283,8 @@ public void removeOwner(CommandContext args,
|
||||
|
||||
String id = args.getString(0);
|
||||
|
||||
RegionManager mgr = plugin.getGlobalRegionManager().get(world);
|
||||
ProtectedRegion region = mgr.getRegion(id);
|
||||
RegionManager manager = plugin.getGlobalRegionManager().get(world);
|
||||
ProtectedRegion region = manager.getRegion(id);
|
||||
|
||||
if (region == null) {
|
||||
throw new CommandException("Could not find a region by that ID.");
|
||||
@ -318,8 +324,11 @@ public void removeOwner(CommandContext args,
|
||||
resolver.createRemoveAllFunction(region.getOwners()));
|
||||
}
|
||||
|
||||
progressCallback(future, sender, "(Please wait... resolving names into UUIDs...)");
|
||||
addCallback(future, messageCallback(sender, "Region '" + id + "' updated.", "Failed to remove owners"));
|
||||
addCallback(future, saveRegionsCallback(sender, mgr, world, true));
|
||||
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")
|
||||
.thenSaveRegionData(manager, world);
|
||||
}
|
||||
}
|
||||
|
@ -19,24 +19,27 @@
|
||||
|
||||
package com.sk89q.worldguard.bukkit.commands;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.IOException;
|
||||
import java.util.logging.Level;
|
||||
import java.util.logging.Logger;
|
||||
|
||||
import org.bukkit.ChatColor;
|
||||
import org.bukkit.command.CommandSender;
|
||||
import org.bukkit.entity.Player;
|
||||
|
||||
import com.sk89q.minecraft.util.commands.Command;
|
||||
import com.sk89q.minecraft.util.commands.CommandContext;
|
||||
import com.sk89q.minecraft.util.commands.CommandException;
|
||||
import com.sk89q.minecraft.util.commands.CommandPermissions;
|
||||
import com.sk89q.odeum.task.Task;
|
||||
import com.sk89q.odeum.task.TaskStateComparator;
|
||||
import com.sk89q.worldguard.bukkit.LoggerToChatHandler;
|
||||
import com.sk89q.worldguard.bukkit.ReportWriter;
|
||||
import com.sk89q.worldguard.bukkit.WorldGuardPlugin;
|
||||
import com.sk89q.worldguard.util.PastebinPoster;
|
||||
import com.sk89q.worldguard.util.PastebinPoster.PasteCallback;
|
||||
import org.bukkit.ChatColor;
|
||||
import org.bukkit.command.CommandSender;
|
||||
import org.bukkit.entity.Player;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.IOException;
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
import java.util.logging.Level;
|
||||
import java.util.logging.Logger;
|
||||
|
||||
public class WorldGuardCommands {
|
||||
private final WorldGuardPlugin plugin;
|
||||
@ -56,6 +59,11 @@ public void version(CommandContext args, CommandSender sender) throws CommandExc
|
||||
@Command(aliases = {"reload"}, desc = "Reload WorldGuard configuration", max = 0)
|
||||
@CommandPermissions({"worldguard.reload"})
|
||||
public void reload(CommandContext args, CommandSender sender) throws CommandException {
|
||||
// TODO: This is subject to a race condition, but at least other commands are not being processed concurrently
|
||||
List<Task<?>> tasks = plugin.getSupervisor().getTasks();
|
||||
if (!tasks.isEmpty()) {
|
||||
throw new CommandException("There are currently pending tasks. Use /wg running and /wg cancelall to monitor and cancel these tasks first.");
|
||||
}
|
||||
|
||||
LoggerToChatHandler handler = null;
|
||||
Logger minecraftLogger = null;
|
||||
@ -135,4 +143,52 @@ public void flushStates(CommandContext args, CommandSender sender) throws Comman
|
||||
}
|
||||
}
|
||||
|
||||
@Command(aliases = {"cancelall"}, flags = "f", desc = "Cancel all running tasks", max = 0)
|
||||
@CommandPermissions("worldguard.cancel.all")
|
||||
public void cancelAllTasks(CommandContext args, CommandSender sender) throws CommandException {
|
||||
List<Task<?>> tasks = plugin.getSupervisor().getTasks();
|
||||
|
||||
boolean force = args.hasFlag('f');
|
||||
if (force && !plugin.hasPermission(sender, "worldguard.cancel.force")) {
|
||||
throw new CommandException("You are not permitted to force cancel.");
|
||||
}
|
||||
|
||||
if (!tasks.isEmpty()) {
|
||||
for (Task<?> task : tasks) {
|
||||
task.cancel(force);
|
||||
sender.sendMessage(ChatColor.YELLOW + "Cancelled: " + ChatColor.WHITE + task.getName());
|
||||
}
|
||||
} else {
|
||||
sender.sendMessage(ChatColor.YELLOW + "There are currently no running tasks.");
|
||||
}
|
||||
}
|
||||
|
||||
@Command(aliases = {"running", "queue"}, desc = "List running tasks", max = 0)
|
||||
@CommandPermissions("worldguard.running")
|
||||
public void listRunningTasks(CommandContext args, CommandSender sender) throws CommandException {
|
||||
List<Task<?>> tasks = plugin.getSupervisor().getTasks();
|
||||
|
||||
if (!tasks.isEmpty()) {
|
||||
Collections.sort(tasks, new TaskStateComparator());
|
||||
StringBuilder builder = new StringBuilder();
|
||||
builder.append(ChatColor.GRAY);
|
||||
builder.append("\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550");
|
||||
builder.append(" Running tasks ");
|
||||
builder.append("\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550");
|
||||
builder.append("\n").append(ChatColor.GRAY).append("Note: Some 'running' tasks may be waiting to be start.");
|
||||
for (Task task : tasks) {
|
||||
builder.append("\n");
|
||||
builder.append(ChatColor.BLUE).append("(").append(task.getState().name()).append(") ");
|
||||
builder.append(ChatColor.YELLOW);
|
||||
builder.append(CommandUtils.getOwnerName(task.getOwner()));
|
||||
builder.append(": ");
|
||||
builder.append(ChatColor.WHITE);
|
||||
builder.append(task.getName());
|
||||
}
|
||||
sender.sendMessage(builder.toString());
|
||||
} else {
|
||||
sender.sendMessage(ChatColor.YELLOW + "There are currently no running tasks.");
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -1,181 +0,0 @@
|
||||
/*
|
||||
* WorldGuard, a suite of tools for Minecraft
|
||||
* Copyright (C) sk89q <http://www.sk89q.com>
|
||||
* Copyright (C) WorldGuard team and contributors
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify it
|
||||
* under the terms of the GNU Lesser General Public License as published by the
|
||||
* Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License
|
||||
* for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
package com.sk89q.worldguard.internal.protection.database.mysql;
|
||||
|
||||
import com.google.common.collect.Lists;
|
||||
import com.sk89q.worldguard.protection.databases.RegionDBUtil;
|
||||
import com.sk89q.worldguard.util.io.Closer;
|
||||
|
||||
import javax.annotation.Nullable;
|
||||
import java.sql.Connection;
|
||||
import java.sql.PreparedStatement;
|
||||
import java.sql.ResultSet;
|
||||
import java.sql.SQLException;
|
||||
import java.sql.Statement;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collection;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.UUID;
|
||||
|
||||
import static com.google.common.base.Preconditions.checkNotNull;
|
||||
|
||||
abstract class UserToIdCache<V> extends AbstractJob {
|
||||
|
||||
private static final int MAX_NUMBER_PER_QUERY = 100;
|
||||
|
||||
private final Map<V, Integer> cache = new HashMap<V, Integer>();
|
||||
private final String fieldName;
|
||||
|
||||
protected UserToIdCache(MySQLDatabaseImpl database, Connection conn, String fieldName) {
|
||||
super(database, conn);
|
||||
this.fieldName = fieldName;
|
||||
}
|
||||
|
||||
protected abstract String fromType(V o);
|
||||
|
||||
protected abstract V toType(String o);
|
||||
|
||||
protected abstract V toKey(V object);
|
||||
|
||||
@Nullable
|
||||
public Integer find(V object) {
|
||||
return cache.get(object);
|
||||
}
|
||||
|
||||
public void fetch(Collection<V> entries) throws SQLException {
|
||||
checkNotNull(entries);
|
||||
|
||||
// Get a list of missing entries
|
||||
List<V> fetchList = new ArrayList<V>();
|
||||
for (V entry : entries) {
|
||||
if (!cache.containsKey(toKey(entry))) {
|
||||
fetchList.add(entry);
|
||||
}
|
||||
}
|
||||
|
||||
if (fetchList.isEmpty()) {
|
||||
return; // Nothing to do
|
||||
}
|
||||
|
||||
// Search for entries
|
||||
for (List<V> partition : Lists.partition(fetchList, MAX_NUMBER_PER_QUERY)) {
|
||||
Closer closer = Closer.create();
|
||||
try {
|
||||
PreparedStatement statement = closer.register(conn.prepareStatement(
|
||||
String.format(
|
||||
"SELECT `user`.`id`, `user`.`" + fieldName + "` " +
|
||||
"FROM `" + config.sqlTablePrefix + "user` AS `user` " +
|
||||
"WHERE `" + fieldName + "` IN (%s)",
|
||||
RegionDBUtil.preparePlaceHolders(partition.size()))));
|
||||
|
||||
String[] values = new String[partition.size()];
|
||||
int i = 0;
|
||||
for (V entry : partition) {
|
||||
values[i] = fromType(entry);
|
||||
i++;
|
||||
}
|
||||
|
||||
RegionDBUtil.setValues(statement, values);
|
||||
ResultSet results = closer.register(statement.executeQuery());
|
||||
while (results.next()) {
|
||||
cache.put(toKey(toType(results.getString(fieldName))), results.getInt("id"));
|
||||
}
|
||||
} finally {
|
||||
closer.closeQuietly();
|
||||
}
|
||||
}
|
||||
|
||||
List<V> missing = new ArrayList<V>();
|
||||
for (V entry : fetchList) {
|
||||
if (!cache.containsKey(toKey(entry))) {
|
||||
missing.add(entry);
|
||||
}
|
||||
}
|
||||
|
||||
// Insert entries that are missing
|
||||
if (!missing.isEmpty()) {
|
||||
Closer closer = Closer.create();
|
||||
try {
|
||||
PreparedStatement statement = closer.register(conn.prepareStatement(
|
||||
"INSERT INTO `" + config.sqlTablePrefix + "user` (`id`, `" + fieldName + "`) VALUES (null, ?)",
|
||||
Statement.RETURN_GENERATED_KEYS));
|
||||
|
||||
for (V entry : missing) {
|
||||
statement.setString(1, fromType(entry));
|
||||
statement.execute();
|
||||
|
||||
ResultSet generatedKeys = statement.getGeneratedKeys();
|
||||
if (generatedKeys.first()) {
|
||||
cache.put(toKey(entry), generatedKeys.getInt(1));
|
||||
} else {
|
||||
logger.warning("Could not get the database ID for user " + entry);
|
||||
}
|
||||
}
|
||||
} finally {
|
||||
closer.closeQuietly();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static class NameToIdCache extends UserToIdCache<String> {
|
||||
protected NameToIdCache(MySQLDatabaseImpl database, Connection conn) {
|
||||
super(database, conn, "name");
|
||||
}
|
||||
|
||||
@Override
|
||||
protected String fromType(String o) {
|
||||
return o;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected String toType(String o) {
|
||||
return o;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected String toKey(String object) {
|
||||
return object.toLowerCase();
|
||||
}
|
||||
}
|
||||
|
||||
static class UUIDToIdCache extends UserToIdCache<UUID> {
|
||||
protected UUIDToIdCache(MySQLDatabaseImpl database, Connection conn) {
|
||||
super(database, conn, "uuid");
|
||||
}
|
||||
|
||||
@Override
|
||||
protected String fromType(UUID o) {
|
||||
return o.toString();
|
||||
}
|
||||
|
||||
@Override
|
||||
protected UUID toType(String o) {
|
||||
return UUID.fromString(o);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected UUID toKey(UUID object) {
|
||||
return object;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
@ -0,0 +1,55 @@
|
||||
/*
|
||||
* WorldGuard, a suite of tools for Minecraft
|
||||
* Copyright (C) sk89q <http://www.sk89q.com>
|
||||
* Copyright (C) WorldGuard team and contributors
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify it
|
||||
* under the terms of the GNU Lesser General Public License as published by the
|
||||
* Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License
|
||||
* for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
package com.sk89q.worldguard.internal.util.sql;
|
||||
|
||||
import java.sql.PreparedStatement;
|
||||
import java.sql.SQLException;
|
||||
|
||||
public class StatementUtils {
|
||||
/**
|
||||
* Creates a comma separated list of PreparedStatement place holders
|
||||
*
|
||||
* @param length The number of wildcards to create
|
||||
* @return A string with {@code length} wildcards for usage in a PreparedStatement
|
||||
*/
|
||||
public static String preparePlaceHolders(int length) {
|
||||
StringBuilder builder = new StringBuilder();
|
||||
for (int i = 0; i < length;) {
|
||||
builder.append("?");
|
||||
if (++i < length) {
|
||||
builder.append(",");
|
||||
}
|
||||
}
|
||||
return builder.toString();
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds all of the parsed values to the PreparedStatement
|
||||
*
|
||||
* @param preparedStatement The preparedStanement to add to
|
||||
* @param values The values to set
|
||||
* @throws SQLException see {@link PreparedStatement#setString(int, String)}
|
||||
*/
|
||||
public static void setValues(PreparedStatement preparedStatement, String... values) throws SQLException {
|
||||
for (int i = 0; i < values.length; i++) {
|
||||
preparedStatement.setString(i + 1, values[i]);
|
||||
}
|
||||
}
|
||||
}
|
@ -25,9 +25,9 @@
|
||||
import com.sk89q.worldguard.bukkit.WorldConfiguration;
|
||||
import com.sk89q.worldguard.bukkit.WorldGuardPlugin;
|
||||
import com.sk89q.worldguard.protection.databases.MySQLDatabase;
|
||||
import com.sk89q.worldguard.protection.databases.YAMLDatabase;
|
||||
import com.sk89q.worldguard.protection.databases.ProtectionDatabase;
|
||||
import com.sk89q.worldguard.protection.databases.ProtectionDatabaseException;
|
||||
import com.sk89q.worldguard.protection.databases.YAMLDatabase;
|
||||
import com.sk89q.worldguard.protection.flags.StateFlag;
|
||||
import com.sk89q.worldguard.protection.managers.PRTreeRegionManager;
|
||||
import com.sk89q.worldguard.protection.managers.RegionManager;
|
||||
|
@ -19,18 +19,7 @@
|
||||
|
||||
package com.sk89q.worldguard.protection.databases;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.FileReader;
|
||||
import java.io.IOException;
|
||||
import java.util.HashMap;
|
||||
import java.util.LinkedHashMap;
|
||||
import java.util.Map;
|
||||
import java.util.logging.Logger;
|
||||
import java.util.regex.Matcher;
|
||||
import java.util.regex.Pattern;
|
||||
|
||||
import au.com.bytecode.opencsv.CSVReader;
|
||||
|
||||
import com.sk89q.worldedit.BlockVector;
|
||||
import com.sk89q.worldedit.Vector;
|
||||
import com.sk89q.worldguard.domains.DefaultDomain;
|
||||
@ -42,11 +31,22 @@
|
||||
import com.sk89q.worldguard.protection.regions.ProtectedRegion.CircularInheritanceException;
|
||||
import com.sk89q.worldguard.util.ArrayReader;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.FileReader;
|
||||
import java.io.IOException;
|
||||
import java.util.HashMap;
|
||||
import java.util.LinkedHashMap;
|
||||
import java.util.Map;
|
||||
import java.util.logging.Logger;
|
||||
import java.util.regex.Matcher;
|
||||
import java.util.regex.Pattern;
|
||||
|
||||
/**
|
||||
* Represents a protected area database that uses CSV files.
|
||||
*
|
||||
* @author sk89q
|
||||
* @deprecated no longer maintained - use {@link YAMLDatabase}
|
||||
*/
|
||||
@Deprecated
|
||||
public class CSVDatabase extends AbstractProtectionDatabase {
|
||||
|
||||
private static final Map<String, StateFlag> legacyFlagCodes = new HashMap<String, StateFlag>();
|
||||
|
@ -1,39 +0,0 @@
|
||||
/*
|
||||
* WorldGuard, a suite of tools for Minecraft
|
||||
* Copyright (C) sk89q <http://www.sk89q.com>
|
||||
* Copyright (C) WorldGuard team and contributors
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify it
|
||||
* under the terms of the GNU Lesser General Public License as published by the
|
||||
* Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License
|
||||
* for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
package com.sk89q.worldguard.protection.databases;
|
||||
|
||||
import com.sk89q.worldguard.util.FatalConfigurationLoadingException;
|
||||
|
||||
public class InvalidTableFormatException extends FatalConfigurationLoadingException {
|
||||
private static final long serialVersionUID = 1L;
|
||||
|
||||
protected String updateFile;
|
||||
|
||||
public InvalidTableFormatException(String updateFile) {
|
||||
super();
|
||||
|
||||
this.updateFile = updateFile;
|
||||
}
|
||||
|
||||
public String toString() {
|
||||
return "You need to update your database to the latest version.\n" +
|
||||
"\t\tPlease see " + this.updateFile;
|
||||
}
|
||||
}
|
@ -19,14 +19,26 @@
|
||||
|
||||
package com.sk89q.worldguard.protection.databases;
|
||||
|
||||
|
||||
import com.google.common.util.concurrent.ListeningExecutorService;
|
||||
import com.sk89q.worldguard.bukkit.ConfigurationManager;
|
||||
import com.sk89q.worldguard.internal.protection.database.mysql.MySQLDatabaseImpl;
|
||||
import com.sk89q.worldguard.protection.databases.mysql.MySQLDatabaseImpl;
|
||||
|
||||
import java.util.logging.Logger;
|
||||
|
||||
/**
|
||||
* A store that persists regions in a MySQL database.
|
||||
*/
|
||||
public class MySQLDatabase extends MySQLDatabaseImpl {
|
||||
|
||||
/**
|
||||
* Create a new instance.
|
||||
*
|
||||
* @param executor the executor to perform loads and saves in
|
||||
* @param config the configuration
|
||||
* @param worldName the world name
|
||||
* @param logger a logger
|
||||
* @throws ProtectionDatabaseException thrown on error
|
||||
*/
|
||||
public MySQLDatabase(ConfigurationManager config, String worldName, Logger logger) throws ProtectionDatabaseException {
|
||||
super(config, worldName, logger);
|
||||
}
|
||||
|
@ -42,7 +42,7 @@ public interface ProtectionDatabase {
|
||||
/**
|
||||
* Load the list of regions into a region manager.
|
||||
*
|
||||
* <p>This call will block and it must be run from the main server thread.</p>
|
||||
* <p>This call will block.</p>
|
||||
*
|
||||
* @param manager The manager to load regions into
|
||||
* @throws ProtectionDatabaseException when an error occurs
|
||||
@ -57,8 +57,6 @@ public interface ProtectionDatabase {
|
||||
* <p>{@code async} is merely a suggestion and it may be ignored by
|
||||
* implementations if it is not supported.</p>
|
||||
*
|
||||
* <p>This method must be run from the main server thread.</p>
|
||||
*
|
||||
* @param manager The manager to load regions into
|
||||
* @param async true to attempt to save the data asynchronously if it is supported
|
||||
*/
|
||||
@ -74,7 +72,7 @@ public interface ProtectionDatabase {
|
||||
/**
|
||||
* Save the list of regions from a region manager.
|
||||
*
|
||||
* <p>This call will block and it must be run from the main server thread.</p>
|
||||
* <p>This call will block.</p>
|
||||
*
|
||||
* @param manager The manager to load regions into
|
||||
* @throws ProtectionDatabaseException when an error occurs
|
||||
@ -89,11 +87,9 @@ public interface ProtectionDatabase {
|
||||
* <p>{@code async} is merely a suggestion and it may be ignored by
|
||||
* implementations if it is not supported.</p>
|
||||
*
|
||||
* <p>This method must be run from the main server thread.</p>
|
||||
*
|
||||
* @param manager The manager to load regions into
|
||||
* @param async true to attempt to save the data asynchronously if it is supported
|
||||
* @throws ProtectionDatabaseException when an error occurs
|
||||
* @throws RejectedExecutionException on rejection
|
||||
*/
|
||||
public ListenableFuture<?> save(RegionManager manager, boolean async) throws RejectedExecutionException;
|
||||
|
||||
|
@ -20,18 +20,18 @@
|
||||
package com.sk89q.worldguard.protection.databases;
|
||||
|
||||
import com.sk89q.worldguard.domains.DefaultDomain;
|
||||
import com.sk89q.worldguard.protection.databases.util.DomainInputResolver;
|
||||
|
||||
import java.sql.PreparedStatement;
|
||||
import java.sql.SQLException;
|
||||
import java.util.regex.Matcher;
|
||||
import java.util.regex.Pattern;
|
||||
|
||||
/**
|
||||
* Various utility functions for parsing region databases.
|
||||
*
|
||||
* @author sk89q
|
||||
*
|
||||
* @deprecated use {@link DomainInputResolver}
|
||||
*/
|
||||
public class RegionDBUtil {
|
||||
@Deprecated
|
||||
public final class RegionDBUtil {
|
||||
|
||||
private static Pattern groupPattern = Pattern.compile("(?i)^[G]:(.+)$");
|
||||
|
||||
@ -45,9 +45,10 @@ private RegionDBUtil() {
|
||||
* @param domain The domain to add to
|
||||
* @param split The {@link String[]} containing names to add to {@code domain}
|
||||
* @param startIndex The beginning index in the array
|
||||
* @deprecated use {@link DomainInputResolver}
|
||||
*/
|
||||
public static void addToDomain(DefaultDomain domain, String[] split,
|
||||
int startIndex) {
|
||||
@Deprecated
|
||||
public static void addToDomain(DefaultDomain domain, String[] split, int startIndex) {
|
||||
for (int i = startIndex; i < split.length; i++) {
|
||||
String s = split[i];
|
||||
Matcher m = groupPattern.matcher(s);
|
||||
@ -65,9 +66,10 @@ public static void addToDomain(DefaultDomain domain, String[] split,
|
||||
* @param domain The domain to remove from
|
||||
* @param split The {@link String[]} containing names to remove from {@code domain}
|
||||
* @param startIndex The beginning index in the array
|
||||
* @deprecated use {@link DomainInputResolver}
|
||||
*/
|
||||
public static void removeFromDomain(DefaultDomain domain, String[] split,
|
||||
int startIndex) {
|
||||
@Deprecated
|
||||
public static void removeFromDomain(DefaultDomain domain, String[] split, int startIndex) {
|
||||
for (int i = startIndex; i < split.length; i++) {
|
||||
String s = split[i];
|
||||
Matcher m = groupPattern.matcher(s);
|
||||
@ -85,7 +87,9 @@ public static void removeFromDomain(DefaultDomain domain, String[] split,
|
||||
* @param split The array of names to add
|
||||
* @param startIndex The beginning index in the array
|
||||
* @return The resulting DefaultDomain
|
||||
* @deprecated use {@link DomainInputResolver}
|
||||
*/
|
||||
@Deprecated
|
||||
public static DefaultDomain parseDomainString(String[] split, int startIndex) {
|
||||
DefaultDomain domain = new DefaultDomain();
|
||||
|
||||
@ -101,34 +105,5 @@ public static DefaultDomain parseDomainString(String[] split, int startIndex) {
|
||||
|
||||
return domain;
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a comma separated list of PreparedStatement place holders
|
||||
*
|
||||
* @param length The number of wildcards to create
|
||||
* @return A string with {@code length} wildcards for usage in a PreparedStatement
|
||||
*/
|
||||
public static String preparePlaceHolders(int length) {
|
||||
StringBuilder builder = new StringBuilder();
|
||||
for (int i = 0; i < length;) {
|
||||
builder.append("?");
|
||||
if (++i < length) {
|
||||
builder.append(",");
|
||||
}
|
||||
}
|
||||
return builder.toString();
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds all of the parsed values to the PreparedStatement
|
||||
*
|
||||
* @param preparedStatement The preparedStanement to add to
|
||||
* @param values The values to set
|
||||
* @throws SQLException see {@link PreparedStatement#setString(int, String)}
|
||||
*/
|
||||
public static void setValues(PreparedStatement preparedStatement, String... values) throws SQLException {
|
||||
for (int i = 0; i < values.length; i++) {
|
||||
preparedStatement.setString(i + 1, values[i]);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -52,6 +52,9 @@
|
||||
import java.util.logging.Level;
|
||||
import java.util.logging.Logger;
|
||||
|
||||
/**
|
||||
* A store that persists regions in a YAML-encoded file.
|
||||
*/
|
||||
public class YAMLDatabase extends AbstractAsynchronousDatabase {
|
||||
|
||||
/**
|
||||
@ -62,7 +65,15 @@ public class YAMLDatabase extends AbstractAsynchronousDatabase {
|
||||
private Map<String, ProtectedRegion> regions;
|
||||
private final File file;
|
||||
private final Logger logger;
|
||||
|
||||
|
||||
/**
|
||||
* Create a new instance.
|
||||
*
|
||||
* @param file the file
|
||||
* @param logger a logger
|
||||
* @throws ProtectionDatabaseException
|
||||
* @throws FileNotFoundException
|
||||
*/
|
||||
public YAMLDatabase(File file, Logger logger) throws ProtectionDatabaseException, FileNotFoundException {
|
||||
this.logger = logger;
|
||||
this.file = file;
|
||||
@ -89,9 +100,9 @@ public void performLoad() throws ProtectionDatabaseException {
|
||||
} catch (IOException e) {
|
||||
throw new ProtectionDatabaseException(e);
|
||||
}
|
||||
|
||||
|
||||
Map<String, YAMLNode> regionData = config.getNodes("regions");
|
||||
|
||||
|
||||
// No regions are even configured
|
||||
if (regionData == null) {
|
||||
this.regions = new HashMap<String, ProtectedRegion>();
|
||||
@ -108,14 +119,14 @@ public void performLoad() throws ProtectionDatabaseException {
|
||||
|
||||
Map<String,ProtectedRegion> regions = new HashMap<String,ProtectedRegion>();
|
||||
Map<ProtectedRegion,String> parentSets = new LinkedHashMap<ProtectedRegion, String>();
|
||||
|
||||
|
||||
for (Map.Entry<String, YAMLNode> entry : regionData.entrySet()) {
|
||||
String id = entry.getKey().toLowerCase().replace(".", "");
|
||||
YAMLNode node = entry.getValue();
|
||||
|
||||
String type = node.getString("type");
|
||||
ProtectedRegion region;
|
||||
|
||||
|
||||
try {
|
||||
if (type == null) {
|
||||
logger.warning("Undefined region type for region '" + id + "'!\n" +
|
||||
@ -139,14 +150,14 @@ public void performLoad() throws ProtectionDatabaseException {
|
||||
"Here is what the region data looks like:\n\n" + dumpAsYaml(entry.getValue().getMap()) + "\n");
|
||||
continue;
|
||||
}
|
||||
|
||||
|
||||
Integer priority = checkNonNull(node.getInt("priority"));
|
||||
region.setPriority(priority);
|
||||
setFlags(region, node.getNode("flags"));
|
||||
region.setOwners(parseDomain(node.getNode("owners")));
|
||||
region.setMembers(parseDomain(node.getNode("members")));
|
||||
regions.put(id, region);
|
||||
|
||||
|
||||
String parentId = node.getString("parent");
|
||||
if (parentId != null) {
|
||||
parentSets.put(region, parentId);
|
||||
@ -154,11 +165,11 @@ public void performLoad() throws ProtectionDatabaseException {
|
||||
} catch (NullPointerException e) {
|
||||
logger.log(Level.WARNING,
|
||||
"Unexpected NullPointerException encountered during parsing for the region '" + id + "'!\n" +
|
||||
"Here is what the region data looks like:\n\n" + dumpAsYaml(entry.getValue().getMap()) +
|
||||
"\n\nNote: This region will disappear as a result!", e);
|
||||
"Here is what the region data looks like:\n\n" + dumpAsYaml(entry.getValue().getMap()) +
|
||||
"\n\nNote: This region will disappear as a result!", e);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// Relink parents
|
||||
for (Map.Entry<ProtectedRegion, String> entry : parentSets.entrySet()) {
|
||||
ProtectedRegion parent = regions.get(entry.getValue());
|
||||
@ -172,23 +183,23 @@ public void performLoad() throws ProtectionDatabaseException {
|
||||
logger.warning("Unknown region parent: " + entry.getValue());
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
this.regions = regions;
|
||||
}
|
||||
|
||||
|
||||
private <V> V checkNonNull(V val) throws NullPointerException {
|
||||
if (val == null) {
|
||||
throw new NullPointerException();
|
||||
}
|
||||
|
||||
|
||||
return val;
|
||||
}
|
||||
|
||||
|
||||
private void setFlags(ProtectedRegion region, YAMLNode flagsData) {
|
||||
if (flagsData == null) {
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
// @TODO: Make this better
|
||||
for (Flag<?> flag : DefaultFlag.getFlags()) {
|
||||
if (flag == null) {
|
||||
@ -201,16 +212,16 @@ private void setFlags(ProtectedRegion region, YAMLNode flagsData) {
|
||||
if (o != null) {
|
||||
setFlag(region, flag, o);
|
||||
}
|
||||
|
||||
|
||||
if (flag.getRegionGroupFlag() != null) {
|
||||
Object o2 = flagsData.getProperty(flag.getRegionGroupFlag().getName());
|
||||
Object o2 = flagsData.getProperty(flag.getRegionGroupFlag().getName());
|
||||
if (o2 != null) {
|
||||
setFlag(region, flag.getRegionGroupFlag(), o2);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
private <T> void setFlag(ProtectedRegion region, Flag<T> flag, Object rawValue) {
|
||||
T val = flag.unmarshal(rawValue);
|
||||
if (val == null) {
|
||||
@ -220,13 +231,13 @@ private <T> void setFlag(ProtectedRegion region, Flag<T> flag, Object rawValue)
|
||||
}
|
||||
region.setFlag(flag, val);
|
||||
}
|
||||
|
||||
|
||||
@SuppressWarnings("deprecation")
|
||||
private DefaultDomain parseDomain(YAMLNode node) {
|
||||
if (node == null) {
|
||||
return new DefaultDomain();
|
||||
}
|
||||
|
||||
|
||||
DefaultDomain domain = new DefaultDomain();
|
||||
|
||||
for (String name : node.getStringList("players", null)) {
|
||||
@ -240,11 +251,11 @@ private DefaultDomain parseDomain(YAMLNode node) {
|
||||
logger.log(Level.WARNING, "Failed to parse UUID '" + stringId +"'", e);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
for (String name : node.getStringList("groups", null)) {
|
||||
domain.addGroup(name);
|
||||
}
|
||||
|
||||
|
||||
return domain;
|
||||
}
|
||||
|
||||
@ -307,18 +318,18 @@ protected void performSave() {
|
||||
"#");
|
||||
config.save();
|
||||
}
|
||||
|
||||
|
||||
private Map<String, Object> getFlagData(ProtectedRegion region) {
|
||||
Map<String, Object> flagData = new HashMap<String, Object>();
|
||||
|
||||
|
||||
for (Map.Entry<Flag<?>, Object> entry : region.getFlags().entrySet()) {
|
||||
Flag<?> flag = entry.getKey();
|
||||
addMarshalledFlag(flagData, flag, entry.getValue());
|
||||
}
|
||||
|
||||
|
||||
return flagData;
|
||||
}
|
||||
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
private <V> void addMarshalledFlag(Map<String, Object> flagData, Flag<V> flag, Object val) {
|
||||
if (val == null) {
|
||||
@ -327,7 +338,7 @@ private <V> void addMarshalledFlag(Map<String, Object> flagData, Flag<V> flag, O
|
||||
|
||||
flagData.put(flag.getName(), flag.marshal((V) val));
|
||||
}
|
||||
|
||||
|
||||
@SuppressWarnings("deprecation")
|
||||
private Map<String, Object> getDomainData(DefaultDomain domain) {
|
||||
Map<String, Object> domainData = new HashMap<String, Object>();
|
||||
@ -335,21 +346,21 @@ private Map<String, Object> getDomainData(DefaultDomain domain) {
|
||||
setDomainData(domainData, "players", domain.getPlayers());
|
||||
setDomainData(domainData, "unique-ids", domain.getUniqueIds());
|
||||
setDomainData(domainData, "groups", domain.getGroups());
|
||||
|
||||
|
||||
return domainData;
|
||||
}
|
||||
|
||||
|
||||
private void setDomainData(Map<String, Object> domainData, String key, Set<?> domain) {
|
||||
if (domain.isEmpty()) {
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
List<String> list = new ArrayList<String>();
|
||||
|
||||
|
||||
for (Object str : domain) {
|
||||
list.add(String.valueOf(str));
|
||||
}
|
||||
|
||||
|
||||
domainData.put(key, list);
|
||||
}
|
||||
|
||||
@ -384,5 +395,5 @@ private static String dumpAsYaml(Object object) {
|
||||
return "<error while dumping object>";
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
@ -1,62 +1,62 @@
|
||||
/*
|
||||
* WorldGuard, a suite of tools for Minecraft
|
||||
* Copyright (C) sk89q <http://www.sk89q.com>
|
||||
* Copyright (C) WorldGuard team and contributors
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify it
|
||||
* under the terms of the GNU Lesser General Public License as published by the
|
||||
* Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License
|
||||
* for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
package com.sk89q.worldguard.protection.databases.migrators;
|
||||
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
|
||||
import com.sk89q.worldguard.protection.databases.ProtectionDatabase;
|
||||
import com.sk89q.worldguard.protection.databases.ProtectionDatabaseException;
|
||||
import com.sk89q.worldguard.protection.regions.ProtectedRegion;
|
||||
|
||||
public abstract class AbstractDatabaseMigrator implements DatabaseMigrator {
|
||||
|
||||
private static HashMap<MigratorKey, Class<? extends AbstractDatabaseMigrator>> migrators =
|
||||
new HashMap<MigratorKey, Class<? extends AbstractDatabaseMigrator>>();
|
||||
|
||||
public static Map<MigratorKey, Class<? extends AbstractDatabaseMigrator>> getMigrators() {
|
||||
if (!migrators.isEmpty()) return migrators;
|
||||
|
||||
AbstractDatabaseMigrator.migrators.put(new MigratorKey("mysql", "yaml"), MySQLToYAMLMigrator.class);
|
||||
AbstractDatabaseMigrator.migrators.put(new MigratorKey("yaml", "mysql"), YAMLToMySQLMigrator.class);
|
||||
|
||||
return migrators;
|
||||
}
|
||||
|
||||
protected abstract Set<String> getWorldsFromOld() throws MigrationException;
|
||||
|
||||
protected abstract Map<String, ProtectedRegion> getRegionsForWorldFromOld(String world) throws MigrationException;
|
||||
|
||||
protected abstract ProtectionDatabase getNewWorldStorage(String world) throws MigrationException;
|
||||
|
||||
public void migrate() throws MigrationException {
|
||||
for (String world : this.getWorldsFromOld()) {
|
||||
ProtectionDatabase database = this.getNewWorldStorage(world);
|
||||
database.setRegions(this.getRegionsForWorldFromOld(world));
|
||||
|
||||
try {
|
||||
database.save();
|
||||
} catch (ProtectionDatabaseException e) {
|
||||
throw new MigrationException(e);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
/*
|
||||
* WorldGuard, a suite of tools for Minecraft
|
||||
* Copyright (C) sk89q <http://www.sk89q.com>
|
||||
* Copyright (C) WorldGuard team and contributors
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify it
|
||||
* under the terms of the GNU Lesser General Public License as published by the
|
||||
* Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License
|
||||
* for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
package com.sk89q.worldguard.protection.databases.migrator;
|
||||
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
|
||||
import com.sk89q.worldguard.protection.databases.ProtectionDatabase;
|
||||
import com.sk89q.worldguard.protection.databases.ProtectionDatabaseException;
|
||||
import com.sk89q.worldguard.protection.regions.ProtectedRegion;
|
||||
|
||||
public abstract class AbstractDatabaseMigrator implements DatabaseMigrator {
|
||||
|
||||
private static HashMap<MigratorKey, Class<? extends AbstractDatabaseMigrator>> migrators =
|
||||
new HashMap<MigratorKey, Class<? extends AbstractDatabaseMigrator>>();
|
||||
|
||||
public static Map<MigratorKey, Class<? extends AbstractDatabaseMigrator>> getMigrators() {
|
||||
if (!migrators.isEmpty()) return migrators;
|
||||
|
||||
AbstractDatabaseMigrator.migrators.put(new MigratorKey("mysql", "yaml"), MySQLToYAMLMigrator.class);
|
||||
AbstractDatabaseMigrator.migrators.put(new MigratorKey("yaml", "mysql"), YAMLToMySQLMigrator.class);
|
||||
|
||||
return migrators;
|
||||
}
|
||||
|
||||
protected abstract Set<String> getWorldsFromOld() throws MigrationException;
|
||||
|
||||
protected abstract Map<String, ProtectedRegion> getRegionsForWorldFromOld(String world) throws MigrationException;
|
||||
|
||||
protected abstract ProtectionDatabase getNewWorldStorage(String world) throws MigrationException;
|
||||
|
||||
public void migrate() throws MigrationException {
|
||||
for (String world : this.getWorldsFromOld()) {
|
||||
ProtectionDatabase database = this.getNewWorldStorage(world);
|
||||
database.setRegions(this.getRegionsForWorldFromOld(world));
|
||||
|
||||
try {
|
||||
database.save();
|
||||
} catch (ProtectionDatabaseException e) {
|
||||
throw new MigrationException(e);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
@ -1,31 +1,31 @@
|
||||
/*
|
||||
* WorldGuard, a suite of tools for Minecraft
|
||||
* Copyright (C) sk89q <http://www.sk89q.com>
|
||||
* Copyright (C) WorldGuard team and contributors
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify it
|
||||
* under the terms of the GNU Lesser General Public License as published by the
|
||||
* Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License
|
||||
* for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
package com.sk89q.worldguard.protection.databases.migrators;
|
||||
|
||||
/**
|
||||
* Represents a method of converting from one database to another.
|
||||
*
|
||||
* @author Nicholas Steicke
|
||||
*/
|
||||
public interface DatabaseMigrator {
|
||||
|
||||
public void migrate() throws MigrationException;
|
||||
}
|
||||
|
||||
/*
|
||||
* WorldGuard, a suite of tools for Minecraft
|
||||
* Copyright (C) sk89q <http://www.sk89q.com>
|
||||
* Copyright (C) WorldGuard team and contributors
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify it
|
||||
* under the terms of the GNU Lesser General Public License as published by the
|
||||
* Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License
|
||||
* for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
package com.sk89q.worldguard.protection.databases.migrator;
|
||||
|
||||
/**
|
||||
* Represents a method of converting from one database to another.
|
||||
*
|
||||
* @author Nicholas Steicke
|
||||
*/
|
||||
public interface DatabaseMigrator {
|
||||
|
||||
public void migrate() throws MigrationException;
|
||||
}
|
||||
|
@ -1,40 +1,40 @@
|
||||
/*
|
||||
* WorldGuard, a suite of tools for Minecraft
|
||||
* Copyright (C) sk89q <http://www.sk89q.com>
|
||||
* Copyright (C) WorldGuard team and contributors
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify it
|
||||
* under the terms of the GNU Lesser General Public License as published by the
|
||||
* Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License
|
||||
* for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
package com.sk89q.worldguard.protection.databases.migrators;
|
||||
|
||||
public class MigrationException extends Exception {
|
||||
private static final long serialVersionUID = 1L;
|
||||
|
||||
public MigrationException() {
|
||||
super();
|
||||
}
|
||||
|
||||
public MigrationException(String message) {
|
||||
super(message);
|
||||
}
|
||||
|
||||
public MigrationException(String message, Throwable cause) {
|
||||
super(message, cause);
|
||||
}
|
||||
|
||||
public MigrationException(Throwable cause) {
|
||||
super(cause);
|
||||
}
|
||||
}
|
||||
/*
|
||||
* WorldGuard, a suite of tools for Minecraft
|
||||
* Copyright (C) sk89q <http://www.sk89q.com>
|
||||
* Copyright (C) WorldGuard team and contributors
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify it
|
||||
* under the terms of the GNU Lesser General Public License as published by the
|
||||
* Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License
|
||||
* for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
package com.sk89q.worldguard.protection.databases.migrator;
|
||||
|
||||
public class MigrationException extends Exception {
|
||||
private static final long serialVersionUID = 1L;
|
||||
|
||||
public MigrationException() {
|
||||
super();
|
||||
}
|
||||
|
||||
public MigrationException(String message) {
|
||||
super(message);
|
||||
}
|
||||
|
||||
public MigrationException(String message, Throwable cause) {
|
||||
super(message, cause);
|
||||
}
|
||||
|
||||
public MigrationException(Throwable cause) {
|
||||
super(cause);
|
||||
}
|
||||
}
|
@ -1,43 +1,43 @@
|
||||
/*
|
||||
* WorldGuard, a suite of tools for Minecraft
|
||||
* Copyright (C) sk89q <http://www.sk89q.com>
|
||||
* Copyright (C) WorldGuard team and contributors
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify it
|
||||
* under the terms of the GNU Lesser General Public License as published by the
|
||||
* Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License
|
||||
* for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
package com.sk89q.worldguard.protection.databases.migrators;
|
||||
|
||||
public class MigratorKey {
|
||||
public final String from;
|
||||
public final String to;
|
||||
|
||||
public MigratorKey(String from, String to) {
|
||||
this.from = from;
|
||||
this.to = to;
|
||||
}
|
||||
|
||||
public boolean equals(Object o) {
|
||||
MigratorKey other = (MigratorKey) o;
|
||||
|
||||
return other.from.equals(this.from) && other.to.equals(this.to);
|
||||
}
|
||||
|
||||
public int hashCode() {
|
||||
int hash = 17;
|
||||
hash = hash * 31 + this.from.hashCode();
|
||||
hash = hash * 31 + this.to.hashCode();
|
||||
return hash;
|
||||
}
|
||||
/*
|
||||
* WorldGuard, a suite of tools for Minecraft
|
||||
* Copyright (C) sk89q <http://www.sk89q.com>
|
||||
* Copyright (C) WorldGuard team and contributors
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify it
|
||||
* under the terms of the GNU Lesser General Public License as published by the
|
||||
* Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License
|
||||
* for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
package com.sk89q.worldguard.protection.databases.migrator;
|
||||
|
||||
public class MigratorKey {
|
||||
public final String from;
|
||||
public final String to;
|
||||
|
||||
public MigratorKey(String from, String to) {
|
||||
this.from = from;
|
||||
this.to = to;
|
||||
}
|
||||
|
||||
public boolean equals(Object o) {
|
||||
MigratorKey other = (MigratorKey) o;
|
||||
|
||||
return other.from.equals(this.from) && other.to.equals(this.to);
|
||||
}
|
||||
|
||||
public int hashCode() {
|
||||
int hash = 17;
|
||||
hash = hash * 31 + this.from.hashCode();
|
||||
hash = hash * 31 + this.to.hashCode();
|
||||
return hash;
|
||||
}
|
||||
}
|
@ -1,97 +1,97 @@
|
||||
/*
|
||||
* WorldGuard, a suite of tools for Minecraft
|
||||
* Copyright (C) sk89q <http://www.sk89q.com>
|
||||
* Copyright (C) WorldGuard team and contributors
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify it
|
||||
* under the terms of the GNU Lesser General Public License as published by the
|
||||
* Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License
|
||||
* for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
package com.sk89q.worldguard.protection.databases.migrators;
|
||||
|
||||
import com.sk89q.worldguard.bukkit.ConfigurationManager;
|
||||
import com.sk89q.worldguard.bukkit.WorldGuardPlugin;
|
||||
import com.sk89q.worldguard.protection.databases.MySQLDatabase;
|
||||
import com.sk89q.worldguard.protection.databases.ProtectionDatabase;
|
||||
import com.sk89q.worldguard.protection.databases.ProtectionDatabaseException;
|
||||
import com.sk89q.worldguard.protection.databases.YAMLDatabase;
|
||||
import com.sk89q.worldguard.protection.regions.ProtectedRegion;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.FileNotFoundException;
|
||||
import java.sql.Connection;
|
||||
import java.sql.DriverManager;
|
||||
import java.sql.ResultSet;
|
||||
import java.sql.SQLException;
|
||||
import java.util.HashSet;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
|
||||
public class MySQLToYAMLMigrator extends AbstractDatabaseMigrator {
|
||||
|
||||
private WorldGuardPlugin plugin;
|
||||
private Set<String> worlds;
|
||||
|
||||
public MySQLToYAMLMigrator(WorldGuardPlugin plugin) throws MigrationException {
|
||||
this.plugin = plugin;
|
||||
this.worlds = new HashSet<String>();
|
||||
|
||||
ConfigurationManager config = plugin.getGlobalStateManager();
|
||||
|
||||
try {
|
||||
Connection conn = DriverManager.getConnection(config.sqlDsn, config.sqlUsername, config.sqlPassword);
|
||||
|
||||
ResultSet worlds = conn.prepareStatement("SELECT `name` FROM `world`;").executeQuery();
|
||||
|
||||
while(worlds.next()) {
|
||||
this.worlds.add(worlds.getString(1));
|
||||
}
|
||||
|
||||
conn.close();
|
||||
} catch (SQLException e) {
|
||||
throw new MigrationException(e);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
protected Set<String> getWorldsFromOld() {
|
||||
return this.worlds;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected Map<String, ProtectedRegion> getRegionsForWorldFromOld(String world) throws MigrationException {
|
||||
ProtectionDatabase oldDatabase;
|
||||
try {
|
||||
oldDatabase = new MySQLDatabase(plugin.getGlobalStateManager(), world, plugin.getLogger());
|
||||
oldDatabase.load();
|
||||
} catch (ProtectionDatabaseException e) {
|
||||
throw new MigrationException(e);
|
||||
}
|
||||
|
||||
return oldDatabase.getRegions();
|
||||
}
|
||||
|
||||
@Override
|
||||
protected ProtectionDatabase getNewWorldStorage(String world) throws MigrationException {
|
||||
try {
|
||||
File file = new File(plugin.getDataFolder(),
|
||||
"worlds" + File.separator + world + File.separator + "regions.yml");
|
||||
|
||||
return new YAMLDatabase(file, plugin.getLogger());
|
||||
} catch (FileNotFoundException e) {
|
||||
throw new MigrationException(e);
|
||||
} catch (ProtectionDatabaseException e) {
|
||||
throw new MigrationException(e);
|
||||
}
|
||||
}
|
||||
}
|
||||
/*
|
||||
* WorldGuard, a suite of tools for Minecraft
|
||||
* Copyright (C) sk89q <http://www.sk89q.com>
|
||||
* Copyright (C) WorldGuard team and contributors
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify it
|
||||
* under the terms of the GNU Lesser General Public License as published by the
|
||||
* Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License
|
||||
* for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
package com.sk89q.worldguard.protection.databases.migrator;
|
||||
|
||||
import com.sk89q.worldguard.bukkit.ConfigurationManager;
|
||||
import com.sk89q.worldguard.bukkit.WorldGuardPlugin;
|
||||
import com.sk89q.worldguard.protection.databases.MySQLDatabase;
|
||||
import com.sk89q.worldguard.protection.databases.YAMLDatabase;
|
||||
import com.sk89q.worldguard.protection.databases.ProtectionDatabase;
|
||||
import com.sk89q.worldguard.protection.databases.ProtectionDatabaseException;
|
||||
import com.sk89q.worldguard.protection.regions.ProtectedRegion;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.FileNotFoundException;
|
||||
import java.sql.Connection;
|
||||
import java.sql.DriverManager;
|
||||
import java.sql.ResultSet;
|
||||
import java.sql.SQLException;
|
||||
import java.util.HashSet;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
|
||||
public class MySQLToYAMLMigrator extends AbstractDatabaseMigrator {
|
||||
|
||||
private WorldGuardPlugin plugin;
|
||||
private Set<String> worlds;
|
||||
|
||||
public MySQLToYAMLMigrator(WorldGuardPlugin plugin) throws MigrationException {
|
||||
this.plugin = plugin;
|
||||
this.worlds = new HashSet<String>();
|
||||
|
||||
ConfigurationManager config = plugin.getGlobalStateManager();
|
||||
|
||||
try {
|
||||
Connection conn = DriverManager.getConnection(config.sqlDsn, config.sqlUsername, config.sqlPassword);
|
||||
|
||||
ResultSet worlds = conn.prepareStatement("SELECT `name` FROM `world`;").executeQuery();
|
||||
|
||||
while(worlds.next()) {
|
||||
this.worlds.add(worlds.getString(1));
|
||||
}
|
||||
|
||||
conn.close();
|
||||
} catch (SQLException e) {
|
||||
throw new MigrationException(e);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
protected Set<String> getWorldsFromOld() {
|
||||
return this.worlds;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected Map<String, ProtectedRegion> getRegionsForWorldFromOld(String world) throws MigrationException {
|
||||
ProtectionDatabase oldDatabase;
|
||||
try {
|
||||
oldDatabase = new MySQLDatabase(plugin.getGlobalStateManager(), world, plugin.getLogger());
|
||||
oldDatabase.load();
|
||||
} catch (ProtectionDatabaseException e) {
|
||||
throw new MigrationException(e);
|
||||
}
|
||||
|
||||
return oldDatabase.getRegions();
|
||||
}
|
||||
|
||||
@Override
|
||||
protected ProtectionDatabase getNewWorldStorage(String world) throws MigrationException {
|
||||
try {
|
||||
File file = new File(plugin.getDataFolder(),
|
||||
"worlds" + File.separator + world + File.separator + "regions.yml");
|
||||
|
||||
return new YAMLDatabase(file, plugin.getLogger());
|
||||
} catch (FileNotFoundException e) {
|
||||
throw new MigrationException(e);
|
||||
} catch (ProtectionDatabaseException e) {
|
||||
throw new MigrationException(e);
|
||||
}
|
||||
}
|
||||
}
|
@ -1,86 +1,86 @@
|
||||
/*
|
||||
* WorldGuard, a suite of tools for Minecraft
|
||||
* Copyright (C) sk89q <http://www.sk89q.com>
|
||||
* Copyright (C) WorldGuard team and contributors
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify it
|
||||
* under the terms of the GNU Lesser General Public License as published by the
|
||||
* Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License
|
||||
* for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
package com.sk89q.worldguard.protection.databases.migrators;
|
||||
|
||||
import com.sk89q.worldguard.bukkit.WorldGuardPlugin;
|
||||
import com.sk89q.worldguard.protection.databases.MySQLDatabase;
|
||||
import com.sk89q.worldguard.protection.databases.ProtectionDatabase;
|
||||
import com.sk89q.worldguard.protection.databases.ProtectionDatabaseException;
|
||||
import com.sk89q.worldguard.protection.databases.YAMLDatabase;
|
||||
import com.sk89q.worldguard.protection.regions.ProtectedRegion;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.FileNotFoundException;
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
|
||||
public class YAMLToMySQLMigrator extends AbstractDatabaseMigrator {
|
||||
|
||||
private WorldGuardPlugin plugin;
|
||||
private HashMap<String,File> regionYamlFiles;
|
||||
|
||||
public YAMLToMySQLMigrator(WorldGuardPlugin plugin) {
|
||||
this.plugin = plugin;
|
||||
|
||||
this.regionYamlFiles = new HashMap<String,File>();
|
||||
|
||||
File files[] = new File(plugin.getDataFolder(), "worlds" + File.separator).listFiles();
|
||||
for (File item : files) {
|
||||
if (item.isDirectory()) {
|
||||
for (File subItem : item.listFiles()) {
|
||||
if (subItem.getName().equals("regions.yml")) {
|
||||
this.regionYamlFiles.put(item.getName(), subItem);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
protected Set<String> getWorldsFromOld() {
|
||||
return this.regionYamlFiles.keySet();
|
||||
}
|
||||
|
||||
@Override
|
||||
protected Map<String, ProtectedRegion> getRegionsForWorldFromOld(String world) throws MigrationException {
|
||||
ProtectionDatabase oldDatabase;
|
||||
try {
|
||||
oldDatabase = new YAMLDatabase(this.regionYamlFiles.get(world), plugin.getLogger());
|
||||
oldDatabase.load();
|
||||
} catch (FileNotFoundException e) {
|
||||
throw new MigrationException(e);
|
||||
} catch (ProtectionDatabaseException e) {
|
||||
throw new MigrationException(e);
|
||||
}
|
||||
|
||||
return oldDatabase.getRegions();
|
||||
}
|
||||
|
||||
@Override
|
||||
protected ProtectionDatabase getNewWorldStorage(String world) throws MigrationException {
|
||||
try {
|
||||
return new MySQLDatabase(plugin.getGlobalStateManager(), world, plugin.getLogger());
|
||||
} catch (ProtectionDatabaseException e) {
|
||||
throw new MigrationException(e);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
/*
|
||||
* WorldGuard, a suite of tools for Minecraft
|
||||
* Copyright (C) sk89q <http://www.sk89q.com>
|
||||
* Copyright (C) WorldGuard team and contributors
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify it
|
||||
* under the terms of the GNU Lesser General Public License as published by the
|
||||
* Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License
|
||||
* for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
package com.sk89q.worldguard.protection.databases.migrator;
|
||||
|
||||
import com.sk89q.worldguard.bukkit.WorldGuardPlugin;
|
||||
import com.sk89q.worldguard.protection.databases.MySQLDatabase;
|
||||
import com.sk89q.worldguard.protection.databases.YAMLDatabase;
|
||||
import com.sk89q.worldguard.protection.databases.ProtectionDatabase;
|
||||
import com.sk89q.worldguard.protection.databases.ProtectionDatabaseException;
|
||||
import com.sk89q.worldguard.protection.regions.ProtectedRegion;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.FileNotFoundException;
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
|
||||
public class YAMLToMySQLMigrator extends AbstractDatabaseMigrator {
|
||||
|
||||
private WorldGuardPlugin plugin;
|
||||
private HashMap<String,File> regionYamlFiles;
|
||||
|
||||
public YAMLToMySQLMigrator(WorldGuardPlugin plugin) {
|
||||
this.plugin = plugin;
|
||||
|
||||
this.regionYamlFiles = new HashMap<String,File>();
|
||||
|
||||
File files[] = new File(plugin.getDataFolder(), "worlds" + File.separator).listFiles();
|
||||
for (File item : files) {
|
||||
if (item.isDirectory()) {
|
||||
for (File subItem : item.listFiles()) {
|
||||
if (subItem.getName().equals("regions.yml")) {
|
||||
this.regionYamlFiles.put(item.getName(), subItem);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
protected Set<String> getWorldsFromOld() {
|
||||
return this.regionYamlFiles.keySet();
|
||||
}
|
||||
|
||||
@Override
|
||||
protected Map<String, ProtectedRegion> getRegionsForWorldFromOld(String world) throws MigrationException {
|
||||
ProtectionDatabase oldDatabase;
|
||||
try {
|
||||
oldDatabase = new YAMLDatabase(this.regionYamlFiles.get(world), plugin.getLogger());
|
||||
oldDatabase.load();
|
||||
} catch (FileNotFoundException e) {
|
||||
throw new MigrationException(e);
|
||||
} catch (ProtectionDatabaseException e) {
|
||||
throw new MigrationException(e);
|
||||
}
|
||||
|
||||
return oldDatabase.getRegions();
|
||||
}
|
||||
|
||||
@Override
|
||||
protected ProtectionDatabase getNewWorldStorage(String world) throws MigrationException {
|
||||
try {
|
||||
return new MySQLDatabase(plugin.getGlobalStateManager(), world, plugin.getLogger());
|
||||
} catch (ProtectionDatabaseException e) {
|
||||
throw new MigrationException(e);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
@ -17,7 +17,7 @@
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
package com.sk89q.worldguard.internal.protection.database.mysql;
|
||||
package com.sk89q.worldguard.protection.databases.mysql;
|
||||
|
||||
import com.sk89q.worldguard.bukkit.ConfigurationManager;
|
||||
import org.yaml.snakeyaml.error.YAMLException;
|
@ -17,8 +17,9 @@
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
package com.sk89q.worldguard.internal.protection.database.mysql;
|
||||
package com.sk89q.worldguard.protection.databases.mysql;
|
||||
|
||||
import com.google.common.util.concurrent.ListeningExecutorService;
|
||||
import com.jolbox.bonecp.BoneCP;
|
||||
import com.jolbox.bonecp.BoneCPConfig;
|
||||
import com.sk89q.worldguard.bukkit.ConfigurationManager;
|
||||
@ -270,7 +271,7 @@ protected void performLoad() throws ProtectionDatabaseException {
|
||||
Connection connection = null;
|
||||
try {
|
||||
connection = getConnection();
|
||||
setRegions(new RegionLoader(this, connection).call());
|
||||
setRegions(new RegionLoader(this, connection).load());
|
||||
} catch (SQLException e) {
|
||||
throw new ProtectionDatabaseException("Failed to load regions database", e);
|
||||
} finally {
|
||||
@ -288,7 +289,7 @@ protected void performSave() throws ProtectionDatabaseException {
|
||||
Connection connection = null;
|
||||
try {
|
||||
connection = getConnection();
|
||||
new RegionCommitter(this, connection, getRegions()).call();
|
||||
new RegionWriter(this, connection, getRegions()).save();
|
||||
} catch (SQLException e) {
|
||||
throw new ProtectionDatabaseException("Failed to save regions database", e);
|
||||
} finally {
|
@ -17,7 +17,7 @@
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
package com.sk89q.worldguard.internal.protection.database.mysql;
|
||||
package com.sk89q.worldguard.protection.databases.mysql;
|
||||
|
||||
import com.sk89q.worldedit.BlockVector;
|
||||
import com.sk89q.worldedit.BlockVector2D;
|
||||
@ -40,9 +40,8 @@
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.UUID;
|
||||
import java.util.concurrent.Callable;
|
||||
|
||||
class RegionLoader extends AbstractJob implements Callable<Map<String, ProtectedRegion>> {
|
||||
class RegionLoader extends AbstractJob {
|
||||
|
||||
/*
|
||||
========= Everything below is a nightmare. =========
|
||||
@ -60,8 +59,7 @@ class RegionLoader extends AbstractJob implements Callable<Map<String, Protected
|
||||
this.worldId = database.getWorldId();
|
||||
}
|
||||
|
||||
@Override
|
||||
public Map<String, ProtectedRegion> call() {
|
||||
public Map<String, ProtectedRegion> load() {
|
||||
parentSets = new HashMap<ProtectedRegion, String>();
|
||||
|
||||
// We load the cuboid regions first, as this is likely to be the
|
@ -17,15 +17,13 @@
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
package com.sk89q.worldguard.internal.protection.database.mysql;
|
||||
package com.sk89q.worldguard.protection.databases.mysql;
|
||||
|
||||
import com.sk89q.worldedit.BlockVector;
|
||||
import com.sk89q.worldedit.BlockVector2D;
|
||||
import com.sk89q.worldguard.domains.DefaultDomain;
|
||||
import com.sk89q.worldguard.internal.protection.database.mysql.UserToIdCache.NameToIdCache;
|
||||
import com.sk89q.worldguard.internal.protection.database.mysql.UserToIdCache.UUIDToIdCache;
|
||||
import com.sk89q.worldguard.internal.util.sql.StatementUtils;
|
||||
import com.sk89q.worldguard.protection.databases.ProtectionDatabaseException;
|
||||
import com.sk89q.worldguard.protection.databases.RegionDBUtil;
|
||||
import com.sk89q.worldguard.protection.flags.Flag;
|
||||
import com.sk89q.worldguard.protection.regions.GlobalProtectedRegion;
|
||||
import com.sk89q.worldguard.protection.regions.ProtectedCuboidRegion;
|
||||
@ -43,33 +41,33 @@
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
import java.util.UUID;
|
||||
import java.util.concurrent.Callable;
|
||||
import java.util.logging.Level;
|
||||
|
||||
import static com.google.common.base.Preconditions.checkNotNull;
|
||||
import static com.sk89q.worldguard.protection.databases.mysql.UserRowCache.NameRowCache;
|
||||
import static com.sk89q.worldguard.protection.databases.mysql.UserRowCache.UUIDRowCache;
|
||||
|
||||
class RegionCommitter extends AbstractJob implements Callable<Object> {
|
||||
class RegionWriter extends AbstractJob {
|
||||
|
||||
/*
|
||||
========= Everything below is a nightmare. =========
|
||||
*/
|
||||
|
||||
private final Map<String, ProtectedRegion> regions;
|
||||
private final NameToIdCache usernameCache;
|
||||
private final UUIDToIdCache uuidCache;
|
||||
private final NameRowCache usernameCache;
|
||||
private final UUIDRowCache uuidCache;
|
||||
private final int worldId;
|
||||
|
||||
RegionCommitter(MySQLDatabaseImpl database, Connection conn, Map<String, ProtectedRegion> regions) {
|
||||
RegionWriter(MySQLDatabaseImpl database, Connection conn, Map<String, ProtectedRegion> regions) {
|
||||
super(database, conn);
|
||||
checkNotNull(regions);
|
||||
this.regions = regions;
|
||||
this.worldId = database.getWorldId();
|
||||
usernameCache = new NameToIdCache(database, conn);
|
||||
uuidCache = new UUIDToIdCache(database, conn);
|
||||
usernameCache = new NameRowCache(database, conn);
|
||||
uuidCache = new UUIDRowCache(database, conn);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Object call() throws SQLException, ProtectionDatabaseException {
|
||||
public void save() throws SQLException, ProtectionDatabaseException {
|
||||
|
||||
/*
|
||||
* As we don't get notified on the creation/removal of regions:
|
||||
@ -183,8 +181,6 @@ public Object call() throws SQLException, ProtectionDatabaseException {
|
||||
closeQuietly(removeRegion);
|
||||
}
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
/*
|
||||
@ -207,11 +203,11 @@ private Map<String,Integer> getGroupIds(String... groupnames) {
|
||||
"`group`.`name` " +
|
||||
"FROM `" + config.sqlTablePrefix + "group` AS `group` " +
|
||||
"WHERE `name` IN (%s)",
|
||||
RegionDBUtil.preparePlaceHolders(groupnames.length)
|
||||
StatementUtils.preparePlaceHolders(groupnames.length)
|
||||
)
|
||||
);
|
||||
|
||||
RegionDBUtil.setValues(findGroupsStatement, groupnames);
|
||||
StatementUtils.setValues(findGroupsStatement, groupnames);
|
||||
|
||||
findGroupsResults = findGroupsStatement.executeQuery();
|
||||
|
@ -0,0 +1,184 @@
|
||||
/*
|
||||
* WorldGuard, a suite of tools for Minecraft
|
||||
* Copyright (C) sk89q <http://www.sk89q.com>
|
||||
* Copyright (C) WorldGuard team and contributors
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify it
|
||||
* under the terms of the GNU Lesser General Public License as published by the
|
||||
* Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License
|
||||
* for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
package com.sk89q.worldguard.protection.databases.mysql;
|
||||
|
||||
import com.google.common.collect.Lists;
|
||||
import com.sk89q.worldguard.internal.util.sql.StatementUtils;
|
||||
import com.sk89q.worldguard.util.io.Closer;
|
||||
|
||||
import javax.annotation.Nullable;
|
||||
import java.sql.Connection;
|
||||
import java.sql.PreparedStatement;
|
||||
import java.sql.ResultSet;
|
||||
import java.sql.SQLException;
|
||||
import java.sql.Statement;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collection;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.UUID;
|
||||
|
||||
import static com.google.common.base.Preconditions.checkNotNull;
|
||||
|
||||
abstract class UserRowCache<V> extends AbstractJob {
|
||||
|
||||
private static final int MAX_NUMBER_PER_QUERY = 100;
|
||||
private static final Object LOCK = new Object();
|
||||
|
||||
private final Map<V, Integer> cache = new HashMap<V, Integer>();
|
||||
private final String fieldName;
|
||||
|
||||
protected UserRowCache(MySQLDatabaseImpl database, Connection conn, String fieldName) {
|
||||
super(database, conn);
|
||||
this.fieldName = fieldName;
|
||||
}
|
||||
|
||||
protected abstract String fromType(V o);
|
||||
|
||||
protected abstract V toType(String o);
|
||||
|
||||
protected abstract V toKey(V object);
|
||||
|
||||
@Nullable
|
||||
public Integer find(V object) {
|
||||
return cache.get(object);
|
||||
}
|
||||
|
||||
public void fetch(Collection<V> entries) throws SQLException {
|
||||
synchronized (LOCK) { // Lock across all cache instances
|
||||
checkNotNull(entries);
|
||||
|
||||
// Get a list of missing entries
|
||||
List<V> fetchList = new ArrayList<V>();
|
||||
for (V entry : entries) {
|
||||
if (!cache.containsKey(toKey(entry))) {
|
||||
fetchList.add(entry);
|
||||
}
|
||||
}
|
||||
|
||||
if (fetchList.isEmpty()) {
|
||||
return; // Nothing to do
|
||||
}
|
||||
|
||||
// Search for entries
|
||||
for (List<V> partition : Lists.partition(fetchList, MAX_NUMBER_PER_QUERY)) {
|
||||
Closer closer = Closer.create();
|
||||
try {
|
||||
PreparedStatement statement = closer.register(conn.prepareStatement(
|
||||
String.format(
|
||||
"SELECT `user`.`id`, `user`.`" + fieldName + "` " +
|
||||
"FROM `" + config.sqlTablePrefix + "user` AS `user` " +
|
||||
"WHERE `" + fieldName + "` IN (%s)",
|
||||
StatementUtils.preparePlaceHolders(partition.size()))));
|
||||
|
||||
String[] values = new String[partition.size()];
|
||||
int i = 0;
|
||||
for (V entry : partition) {
|
||||
values[i] = fromType(entry);
|
||||
i++;
|
||||
}
|
||||
|
||||
StatementUtils.setValues(statement, values);
|
||||
ResultSet results = closer.register(statement.executeQuery());
|
||||
while (results.next()) {
|
||||
cache.put(toKey(toType(results.getString(fieldName))), results.getInt("id"));
|
||||
}
|
||||
} finally {
|
||||
closer.closeQuietly();
|
||||
}
|
||||
}
|
||||
|
||||
List<V> missing = new ArrayList<V>();
|
||||
for (V entry : fetchList) {
|
||||
if (!cache.containsKey(toKey(entry))) {
|
||||
missing.add(entry);
|
||||
}
|
||||
}
|
||||
|
||||
// Insert entries that are missing
|
||||
if (!missing.isEmpty()) {
|
||||
Closer closer = Closer.create();
|
||||
try {
|
||||
PreparedStatement statement = closer.register(conn.prepareStatement(
|
||||
"INSERT INTO `" + config.sqlTablePrefix + "user` (`id`, `" + fieldName + "`) VALUES (null, ?)",
|
||||
Statement.RETURN_GENERATED_KEYS));
|
||||
|
||||
for (V entry : missing) {
|
||||
statement.setString(1, fromType(entry));
|
||||
statement.execute();
|
||||
|
||||
ResultSet generatedKeys = statement.getGeneratedKeys();
|
||||
if (generatedKeys.first()) {
|
||||
cache.put(toKey(entry), generatedKeys.getInt(1));
|
||||
} else {
|
||||
logger.warning("Could not get the database ID for user " + entry);
|
||||
}
|
||||
}
|
||||
} finally {
|
||||
closer.closeQuietly();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static class NameRowCache extends UserRowCache<String> {
|
||||
protected NameRowCache(MySQLDatabaseImpl database, Connection conn) {
|
||||
super(database, conn, "name");
|
||||
}
|
||||
|
||||
@Override
|
||||
protected String fromType(String o) {
|
||||
return o;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected String toType(String o) {
|
||||
return o;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected String toKey(String object) {
|
||||
return object.toLowerCase();
|
||||
}
|
||||
}
|
||||
|
||||
static class UUIDRowCache extends UserRowCache<UUID> {
|
||||
protected UUIDRowCache(MySQLDatabaseImpl database, Connection conn) {
|
||||
super(database, conn, "uuid");
|
||||
}
|
||||
|
||||
@Override
|
||||
protected String fromType(UUID o) {
|
||||
return o.toString();
|
||||
}
|
||||
|
||||
@Override
|
||||
protected UUID toType(String o) {
|
||||
return UUID.fromString(o);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected UUID toKey(UUID object) {
|
||||
return object;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
@ -26,21 +26,24 @@
|
||||
import com.sk89q.worldguard.protection.databases.ProtectionDatabase;
|
||||
import com.sk89q.worldguard.protection.regions.ProtectedRegion;
|
||||
|
||||
import java.util.*;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.TreeSet;
|
||||
import java.util.concurrent.ConcurrentHashMap;
|
||||
import java.util.concurrent.ConcurrentMap;
|
||||
|
||||
/**
|
||||
* A very simple implementation of the region manager that uses a flat list
|
||||
* and iterates through the list to identify applicable regions. This method
|
||||
* is not very efficient.
|
||||
*
|
||||
* @author sk89q
|
||||
*/
|
||||
public class FlatRegionManager extends RegionManager {
|
||||
|
||||
/**
|
||||
* List of protected regions.
|
||||
*/
|
||||
private Map<String, ProtectedRegion> regions;
|
||||
private ConcurrentMap<String, ProtectedRegion> regions = new ConcurrentHashMap<String, ProtectedRegion>();
|
||||
|
||||
/**
|
||||
* Construct the manager.
|
||||
@ -49,7 +52,6 @@ public class FlatRegionManager extends RegionManager {
|
||||
*/
|
||||
public FlatRegionManager(ProtectionDatabase regionLoader) {
|
||||
super(regionLoader);
|
||||
regions = new TreeMap<String, ProtectedRegion>();
|
||||
}
|
||||
|
||||
@Override
|
||||
@ -59,7 +61,7 @@ public Map<String, ProtectedRegion> getRegions() {
|
||||
|
||||
@Override
|
||||
public void setRegions(Map<String, ProtectedRegion> regions) {
|
||||
this.regions = new TreeMap<String, ProtectedRegion>(regions);
|
||||
this.regions = new ConcurrentHashMap<String, ProtectedRegion>(regions);
|
||||
}
|
||||
|
||||
@Override
|
||||
@ -185,7 +187,7 @@ public boolean overlapsUnownedRegion(ProtectedRegion checkRegion, LocalPlayer pl
|
||||
intersectRegions = new ArrayList<ProtectedRegion>();
|
||||
}
|
||||
|
||||
return intersectRegions.size() > 0;
|
||||
return !intersectRegions.isEmpty();
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -30,7 +30,12 @@
|
||||
import org.khelekore.prtree.PRTree;
|
||||
import org.khelekore.prtree.SimpleMBR;
|
||||
|
||||
import java.util.*;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.concurrent.ConcurrentHashMap;
|
||||
import java.util.concurrent.ConcurrentMap;
|
||||
|
||||
public class PRTreeRegionManager extends RegionManager {
|
||||
|
||||
@ -55,7 +60,7 @@ public Map<String, ProtectedRegion> getRegions() {
|
||||
|
||||
@Override
|
||||
public void setRegions(Map<String, ProtectedRegion> regions) {
|
||||
Map<String, ProtectedRegion> newRegions = new TreeMap<String, ProtectedRegion>(regions);
|
||||
ConcurrentMap<String, ProtectedRegion> newRegions = new ConcurrentHashMap<String, ProtectedRegion>(regions);
|
||||
PRTree<ProtectedRegion> tree = new PRTree<ProtectedRegion>(converter, BRANCH_FACTOR);
|
||||
tree.load(newRegions.values());
|
||||
this.data = new RegionsContainer(newRegions, tree);
|
||||
@ -65,8 +70,9 @@ public void setRegions(Map<String, ProtectedRegion> regions) {
|
||||
public void addRegion(ProtectedRegion region) {
|
||||
RegionsContainer data = this.data;
|
||||
data.regions.put(region.getId().toLowerCase(), region);
|
||||
data.tree = new PRTree<ProtectedRegion>(converter, BRANCH_FACTOR);
|
||||
data.tree.load(data.regions.values());
|
||||
PRTree<ProtectedRegion> tree = new PRTree<ProtectedRegion>(converter, BRANCH_FACTOR);
|
||||
tree.load(data.regions.values());
|
||||
this.data = new RegionsContainer(data.regions, tree);
|
||||
}
|
||||
|
||||
@Override
|
||||
@ -95,8 +101,9 @@ public void removeRegion(String id) {
|
||||
}
|
||||
}
|
||||
|
||||
data.tree = new PRTree<ProtectedRegion>(converter, BRANCH_FACTOR);
|
||||
data.tree.load(data.regions.values());
|
||||
PRTree<ProtectedRegion> tree = new PRTree<ProtectedRegion>(converter, BRANCH_FACTOR);
|
||||
tree.load(data.regions.values());
|
||||
this.data = new RegionsContainer(data.regions, tree);
|
||||
}
|
||||
|
||||
@Override
|
||||
@ -197,7 +204,7 @@ public boolean overlapsUnownedRegion(ProtectedRegion checkRegion, LocalPlayer pl
|
||||
intersectRegions = new ArrayList<ProtectedRegion>();
|
||||
}
|
||||
|
||||
return intersectRegions.size() > 0;
|
||||
return !intersectRegions.isEmpty();
|
||||
}
|
||||
|
||||
@Override
|
||||
@ -219,15 +226,15 @@ public int getRegionCountOfPlayer(LocalPlayer player) {
|
||||
}
|
||||
|
||||
private class RegionsContainer {
|
||||
private final Map<String, ProtectedRegion> regions;
|
||||
private PRTree<ProtectedRegion> tree;
|
||||
private final ConcurrentMap<String, ProtectedRegion> regions;
|
||||
private final PRTree<ProtectedRegion> tree;
|
||||
|
||||
private RegionsContainer() {
|
||||
regions = new TreeMap<String, ProtectedRegion>();
|
||||
regions = new ConcurrentHashMap<String, ProtectedRegion>();
|
||||
tree = new PRTree<ProtectedRegion>(converter, BRANCH_FACTOR);
|
||||
}
|
||||
|
||||
private RegionsContainer(Map<String, ProtectedRegion> regions, PRTree<ProtectedRegion> tree) {
|
||||
private RegionsContainer(ConcurrentMap<String, ProtectedRegion> regions, PRTree<ProtectedRegion> tree) {
|
||||
this.regions = regions;
|
||||
this.tree = tree;
|
||||
}
|
||||
|
@ -60,6 +60,7 @@ public RegionManager(ProtectionDatabase loader) {
|
||||
public void load() throws ProtectionDatabaseException {
|
||||
loader.load(this);
|
||||
}
|
||||
|
||||
/**
|
||||
* Load the list of regions. If the regions do not load properly, then
|
||||
* the existing list should be used (as stored previously).
|
||||
|
@ -35,8 +35,6 @@
|
||||
|
||||
/**
|
||||
* Represents a region of any shape and size that can be protected.
|
||||
*
|
||||
* @author sk89q
|
||||
*/
|
||||
public abstract class ProtectedRegion implements Comparable<ProtectedRegion> {
|
||||
|
||||
@ -45,34 +43,11 @@ public abstract class ProtectedRegion implements Comparable<ProtectedRegion> {
|
||||
|
||||
private static final Pattern idPattern = Pattern.compile("^[A-Za-z0-9_,'\\-\\+/]{1,}$");
|
||||
|
||||
/**
|
||||
* Holds the region's ID.
|
||||
*/
|
||||
private String id;
|
||||
|
||||
/**
|
||||
* Priority.
|
||||
*/
|
||||
private int priority = 0;
|
||||
|
||||
/**
|
||||
* Holds the curParent.
|
||||
*/
|
||||
private ProtectedRegion parent;
|
||||
|
||||
/**
|
||||
* List of owners.
|
||||
*/
|
||||
private DefaultDomain owners = new DefaultDomain();
|
||||
|
||||
/**
|
||||
* List of members.
|
||||
*/
|
||||
private DefaultDomain members = new DefaultDomain();
|
||||
|
||||
/**
|
||||
* List of flags.
|
||||
*/
|
||||
private Map<Flag<?>, Object> flags = new ConcurrentHashMap<Flag<?>, Object>();
|
||||
|
||||
/**
|
||||
@ -457,8 +432,8 @@ public boolean contains(int x, int y, int z) {
|
||||
/**
|
||||
* Check to see if any of the 2D points are inside this region.
|
||||
*
|
||||
* @param pts
|
||||
* @return
|
||||
* @param pts a list positions
|
||||
* @return true if contained
|
||||
*/
|
||||
public boolean containsAny(List<BlockVector2D> pts) {
|
||||
for (BlockVector2D pt : pts) {
|
||||
@ -477,6 +452,7 @@ public boolean containsAny(List<BlockVector2D> pts) {
|
||||
*
|
||||
* @param other The region to compare to
|
||||
*/
|
||||
@Override
|
||||
public int compareTo(ProtectedRegion other) {
|
||||
if (priority > other.priority) {
|
||||
return -1;
|
||||
@ -598,6 +574,6 @@ public boolean equals(Object obj) {
|
||||
* situation.
|
||||
*/
|
||||
public static class CircularInheritanceException extends Exception {
|
||||
private static final long serialVersionUID = 7479613488496776022L;
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -24,11 +24,9 @@
|
||||
|
||||
/**
|
||||
* Various utility functions for regions.
|
||||
*
|
||||
* @author sk89q
|
||||
*/
|
||||
@Deprecated
|
||||
public class RegionUtil {
|
||||
public final class RegionUtil {
|
||||
|
||||
private RegionUtil() {
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user