Changed WorldEdit to use the new dispatcher.

This commit is contained in:
Albert Pham 2013-06-18 14:51:42 -07:00
parent 04c31262f7
commit 142f5c8e5c
17 changed files with 882 additions and 381 deletions

View File

@ -19,12 +19,13 @@
package com.sk89q.worldedit; package com.sk89q.worldedit;
import com.sk89q.minecraft.util.commands.Command;
import com.sk89q.minecraft.util.commands.CommandsManager;
import java.util.Collections; import java.util.Collections;
import java.util.List; import java.util.List;
import com.sk89q.minecraft.util.commands.Command;
import com.sk89q.minecraft.util.commands.CommandsManager;
import com.sk89q.rebar.command.Dispatcher;
/** /**
* *
* @author sk89q * @author sk89q
@ -83,4 +84,7 @@ public abstract class ServerInterface {
public void onCommandRegistration(List<Command> commands, CommandsManager<LocalPlayer> manager) { public void onCommandRegistration(List<Command> commands, CommandsManager<LocalPlayer> manager) {
onCommandRegistration(commands); onCommandRegistration(commands);
} }
public void registerCommands(Dispatcher dispatcher) {
}
} }

View File

@ -24,7 +24,6 @@ import java.io.File;
import java.io.FileInputStream; import java.io.FileInputStream;
import java.io.IOException; import java.io.IOException;
import java.io.InputStream; import java.io.InputStream;
import java.lang.reflect.Method;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.HashMap; import java.util.HashMap;
import java.util.HashSet; import java.util.HashSet;
@ -32,49 +31,47 @@ import java.util.Iterator;
import java.util.List; import java.util.List;
import java.util.Map; import java.util.Map;
import java.util.Set; import java.util.Set;
import java.util.logging.FileHandler;
import java.util.logging.Level;
import java.util.logging.Logger; import java.util.logging.Logger;
import java.util.regex.Matcher;
import javax.script.ScriptException; import javax.script.ScriptException;
import com.sk89q.minecraft.util.commands.CommandException; import com.sk89q.minecraft.util.commands.CommandException;
import com.sk89q.minecraft.util.commands.CommandLocals;
import com.sk89q.minecraft.util.commands.CommandPermissionsException; import com.sk89q.minecraft.util.commands.CommandPermissionsException;
import com.sk89q.minecraft.util.commands.CommandUsageException;
import com.sk89q.minecraft.util.commands.CommandsManager;
import com.sk89q.minecraft.util.commands.Console;
import com.sk89q.minecraft.util.commands.Logging;
import com.sk89q.minecraft.util.commands.MissingNestedCommandException;
import com.sk89q.minecraft.util.commands.SimpleInjector;
import com.sk89q.minecraft.util.commands.UnhandledCommandException;
import com.sk89q.minecraft.util.commands.WrappedCommandException; import com.sk89q.minecraft.util.commands.WrappedCommandException;
import com.sk89q.util.StringUtil; import com.sk89q.rebar.command.Dispatcher;
import com.sk89q.rebar.command.InvalidUsageException;
import com.sk89q.rebar.command.fluent.CommandGraph;
import com.sk89q.rebar.command.parametric.LegacyCommandsHandler;
import com.sk89q.rebar.command.parametric.ParametricBuilder;
import com.sk89q.worldedit.CuboidClipboard.FlipDirection; import com.sk89q.worldedit.CuboidClipboard.FlipDirection;
import com.sk89q.worldedit.bags.BlockBag; import com.sk89q.worldedit.bags.BlockBag;
import com.sk89q.worldedit.blocks.BaseBlock; import com.sk89q.worldedit.blocks.BaseBlock;
import com.sk89q.worldedit.blocks.BlockType; import com.sk89q.worldedit.blocks.BlockType;
import com.sk89q.worldedit.blocks.ClothColor; import com.sk89q.worldedit.blocks.ClothColor;
import com.sk89q.worldedit.blocks.ItemType;
import com.sk89q.worldedit.blocks.MobSpawnerBlock; import com.sk89q.worldedit.blocks.MobSpawnerBlock;
import com.sk89q.worldedit.blocks.NoteBlock; import com.sk89q.worldedit.blocks.NoteBlock;
import com.sk89q.worldedit.blocks.SignBlock; import com.sk89q.worldedit.blocks.SignBlock;
import com.sk89q.worldedit.blocks.SkullBlock; import com.sk89q.worldedit.blocks.SkullBlock;
import com.sk89q.worldedit.commands.BiomeCommands; import com.sk89q.worldedit.commands.BiomeCommands;
import com.sk89q.worldedit.commands.BrushCommands;
import com.sk89q.worldedit.commands.ChunkCommands; import com.sk89q.worldedit.commands.ChunkCommands;
import com.sk89q.worldedit.commands.ClipboardCommands; import com.sk89q.worldedit.commands.ClipboardCommands;
import com.sk89q.worldedit.commands.GeneralCommands; import com.sk89q.worldedit.commands.GeneralCommands;
import com.sk89q.worldedit.commands.GenerationCommands; import com.sk89q.worldedit.commands.GenerationCommands;
import com.sk89q.worldedit.commands.HistoryCommands; import com.sk89q.worldedit.commands.HistoryCommands;
import com.sk89q.worldedit.commands.InsufficientArgumentsException;
import com.sk89q.worldedit.commands.NavigationCommands; import com.sk89q.worldedit.commands.NavigationCommands;
import com.sk89q.worldedit.commands.RegionCommands; import com.sk89q.worldedit.commands.RegionCommands;
import com.sk89q.worldedit.commands.SchematicCommands;
import com.sk89q.worldedit.commands.ScriptingCommands; import com.sk89q.worldedit.commands.ScriptingCommands;
import com.sk89q.worldedit.commands.SelectionCommands; import com.sk89q.worldedit.commands.SelectionCommands;
import com.sk89q.worldedit.commands.SnapshotCommands;
import com.sk89q.worldedit.commands.SnapshotUtilCommands; import com.sk89q.worldedit.commands.SnapshotUtilCommands;
import com.sk89q.worldedit.commands.SuperPickaxeCommands;
import com.sk89q.worldedit.commands.ToolCommands; import com.sk89q.worldedit.commands.ToolCommands;
import com.sk89q.worldedit.commands.ToolUtilCommands; import com.sk89q.worldedit.commands.ToolUtilCommands;
import com.sk89q.worldedit.commands.UtilityCommands; import com.sk89q.worldedit.commands.UtilityCommands;
import com.sk89q.worldedit.commands.WorldEditCommands;
import com.sk89q.worldedit.masks.BiomeTypeMask; import com.sk89q.worldedit.masks.BiomeTypeMask;
import com.sk89q.worldedit.masks.BlockMask; import com.sk89q.worldedit.masks.BlockMask;
import com.sk89q.worldedit.masks.CombinedMask; import com.sk89q.worldedit.masks.CombinedMask;
@ -99,6 +96,10 @@ import com.sk89q.worldedit.tools.DoubleActionBlockTool;
import com.sk89q.worldedit.tools.DoubleActionTraceTool; import com.sk89q.worldedit.tools.DoubleActionTraceTool;
import com.sk89q.worldedit.tools.Tool; import com.sk89q.worldedit.tools.Tool;
import com.sk89q.worldedit.tools.TraceTool; import com.sk89q.worldedit.tools.TraceTool;
import com.sk89q.worldedit.util.CommandLoggingHandler;
import com.sk89q.worldedit.util.CommandPermissionsHandler;
import com.sk89q.worldedit.util.WorldEditBinding;
import com.sk89q.worldedit.util.WorldEditExceptionConverter;
/** /**
* This class is the main entry point for WorldEdit. All events are routed * This class is the main entry point for WorldEdit. All events are routed
@ -109,186 +110,99 @@ import com.sk89q.worldedit.tools.TraceTool;
* @author sk89q * @author sk89q
*/ */
public class WorldEdit { public class WorldEdit {
/**
* Logger for debugging.
*/
public static final Logger logger = Logger.getLogger("Minecraft.WorldEdit"); public static final Logger logger = Logger.getLogger("Minecraft.WorldEdit");
public final Logger commandLogger = Logger.getLogger("Minecraft.WorldEdit.CommandLogger");
/**
* Holds the current instance of this class, for static access
*/
private static WorldEdit instance; private static WorldEdit instance;
/**
* Holds WorldEdit's version.
*/
private static String version; private static String version;
/**
* Interface to the server.
*/
private final ServerInterface server;
/**
* Configuration. This is a subclass.
*/
private final LocalConfiguration config;
/**
* List of commands.
*/
private final CommandsManager<LocalPlayer> commands;
/** private final ServerInterface server;
* Holds the factory responsible for the creation of edit sessions private final LocalConfiguration config;
*/ private final Dispatcher dispatcher;
private final CommandLoggingHandler commandLogger;
private final HashMap<String, LocalSession> sessions = new HashMap<String, LocalSession>();
private EditSessionFactory editSessionFactory = new EditSessionFactory(); private EditSessionFactory editSessionFactory = new EditSessionFactory();
/**
* Stores a list of WorldEdit sessions, keyed by players' names. Sessions
* persist only for the user's session. On disconnect, the session will be
* removed. Sessions are created only when they are needed and those
* without any WorldEdit abilities or never use WorldEdit in a session will
* not have a session object generated for them.
*/
private final HashMap<String, LocalSession> sessions = new HashMap<String, LocalSession>();
/**
* Initialize statically.
*/
static { static {
getVersion(); getVersion();
} }
/** /**
* Construct an instance of the plugin * Gets the current instance of this class.
*
* @param server
* @param config
*/
public WorldEdit(ServerInterface server, final LocalConfiguration config) {
instance = this;
this.server = server;
this.config = config;
if (!config.logFile.equals("")) {
try {
FileHandler logFileHandler;
logFileHandler = new FileHandler(new File(config.getWorkingDirectory(),
config.logFile).getAbsolutePath(), true);
logFileHandler.setFormatter(new LogFormat());
commandLogger.addHandler(logFileHandler);
} catch (IOException e) {
logger.log(Level.WARNING, "Could not use command log file " + config.logFile + ": "
+ e.getMessage());
}
}
commands = new CommandsManager<LocalPlayer>() {
@Override
protected void checkPermission(LocalPlayer player, Method method) throws CommandException {
if (!player.isPlayer() && !method.isAnnotationPresent(Console.class)) {
throw new UnhandledCommandException();
}
super.checkPermission(player, method);
}
@Override
public boolean hasPermission(LocalPlayer player, String perm) {
return player.hasPermission(perm);
}
@Override
public void invokeMethod(Method parent, String[] args,
LocalPlayer player, Method method, Object instance,
Object[] methodArgs, int level) throws CommandException {
if (config.logCommands) {
final Logging loggingAnnotation = method.getAnnotation(Logging.class);
final Logging.LogMode logMode;
if (loggingAnnotation == null) {
logMode = null;
} else {
logMode = loggingAnnotation.value();
}
String msg = "WorldEdit: " + player.getName();
if (player.isPlayer()) {
msg += " (in \"" + player.getWorld().getName() + "\")";
}
msg += ": " + StringUtil.joinString(args, " ");
if (logMode != null && player.isPlayer()) {
Vector position = player.getPosition();
final LocalSession session = getSession(player);
switch (logMode) {
case PLACEMENT:
try {
position = session.getPlacementPosition(player);
} catch (IncompleteRegionException e) {
break;
}
/* FALL-THROUGH */
case POSITION:
msg += " - Position: " + position;
break;
case ALL:
msg += " - Position: " + position;
/* FALL-THROUGH */
case ORIENTATION_REGION:
msg += " - Orientation: " + player.getCardinalDirection().name();
/* FALL-THROUGH */
case REGION:
try {
msg += " - Region: " + session.getSelection(player.getWorld());
} catch (IncompleteRegionException e) {
break;
}
break;
}
}
commandLogger.info(msg);
}
super.invokeMethod(parent, args, player, method, instance, methodArgs, level);
}
};
commands.setInjector(new SimpleInjector(this));
reg(BiomeCommands.class);
reg(ChunkCommands.class);
reg(ClipboardCommands.class);
reg(GeneralCommands.class);
reg(GenerationCommands.class);
reg(HistoryCommands.class);
reg(NavigationCommands.class);
reg(RegionCommands.class);
reg(ScriptingCommands.class);
reg(SelectionCommands.class);
reg(SnapshotUtilCommands.class);
reg(ToolUtilCommands.class);
reg(ToolCommands.class);
reg(UtilityCommands.class);
}
private void reg(Class<?> clazz) {
server.onCommandRegistration(commands.registerAndReturn(clazz), commands);
}
/**
* Gets the current instance of this class
* *
* @return * <p>An instance is available once a plugin/host has initialized WorldEdit.</p>
*
* @return an instance
*/ */
public static WorldEdit getInstance() { public static WorldEdit getInstance() {
return instance; return instance;
} }
/**
* Construct an instance of the class.
*
* @param server the server interface
* @param config the configuration
*/
public WorldEdit(ServerInterface server, final LocalConfiguration config) {
WorldEdit.instance = this;
this.server = server;
this.config = config;
ParametricBuilder builder = new ParametricBuilder();
builder.addBinding(new WorldEditBinding(this));
builder.attach(new CommandPermissionsHandler());
builder.attach(new WorldEditExceptionConverter(config));
builder.attach(new LegacyCommandsHandler());
builder.attach(commandLogger = new CommandLoggingHandler(this, config));
dispatcher = new CommandGraph()
.builder(builder)
.commands()
.build(new BiomeCommands(this))
.build(new ChunkCommands(this))
.build(new ClipboardCommands(this))
.build(new GeneralCommands(this))
.build(new GenerationCommands(this))
.build(new HistoryCommands(this))
.build(new NavigationCommands(this))
.build(new RegionCommands(this))
.build(new ScriptingCommands(this))
.build(new SelectionCommands(this))
.build(new SnapshotUtilCommands(this))
.build(new ToolUtilCommands(this))
.build(new ToolCommands(this))
.build(new UtilityCommands(this))
.group("worldedit", "we")
.describe("WorldEdit commands")
.build(new WorldEditCommands(this))
.parent()
.group("schematic", "schem", "/schematic", "/schem")
.describe("Schematic commands for saving/loading areas")
.build(new SchematicCommands(this))
.parent()
.group("snapshot", "snap")
.describe("Schematic commands for saving/loading areas")
.build(new SnapshotCommands(this))
.parent()
.group("brush", "br")
.describe("Brushing commands")
.build(new BrushCommands(this))
.parent()
.group("superpickaxe", "pickaxe", "sp")
.describe("Super-pickaxe commands")
.build(new SuperPickaxeCommands(this))
.parent()
.group("tool")
.describe("Bind functions to held items")
.build(new ToolCommands(this))
.parent()
.graph()
.getDispatcher();
server.registerCommands(dispatcher);
}
/** /**
* Gets the LocalSession for a player name if it exists * Gets the LocalSession for a player name if it exists
* *
@ -302,8 +216,8 @@ public class WorldEdit {
/** /**
* Gets the WorldEdit session for a player. * Gets the WorldEdit session for a player.
* *
* @param player * @param player the player
* @return * @return the session
*/ */
public LocalSession getSession(LocalPlayer player) { public LocalSession getSession(LocalPlayer player) {
LocalSession session; LocalSession session;
@ -1149,17 +1063,12 @@ public class WorldEdit {
} }
/** /**
* @return the commands * Get the command dispatcher.
*
* @return the command dispatcher
*/ */
public Map<String, String> getCommands() { public Dispatcher getDispatcher() {
return commands.getCommands(); return dispatcher;
}
/**
* @return the commands
*/
public CommandsManager<LocalPlayer> getCommandsManager() {
return commands;
} }
/** /**
@ -1367,48 +1276,44 @@ public class WorldEdit {
return false; return false;
} }
private static final java.util.regex.Pattern numberFormatExceptionPattern = java.util.regex.Pattern.compile("^For input string: \"(.*)\"$");
/** /**
* * Execute a command.
* @param player *
* @param split * @param player the local player
* @param split the list of arguments
* @return whether the command was processed * @return whether the command was processed
*/ */
public boolean handleCommand(LocalPlayer player, String[] split) { public boolean handleCommand(LocalPlayer player, String[] split) {
split = commandDetection(split);
// No command found!
if (!dispatcher.contains(split[0])) {
return false;
}
CommandLocals locals = new CommandLocals();
locals.put(LocalPlayer.class, player);
long start = System.currentTimeMillis();
try { try {
split = commandDetection(split); dispatcher.call(split, locals);
} catch (CommandPermissionsException e) {
// No command found! player.printError("You don't have permission to do this.");
if (!commands.hasCommand(split[0])) { } catch (InvalidUsageException e) {
return false; player.printError(e.getMessage() + "\nUsage: " + e.getUsage("/"));
} } catch (WrappedCommandException e) {
Throwable t = e.getCause();
LocalSession session = getSession(player); player.printError("Please report this error: [See console]");
EditSession editSession = session.createEditSession(player); player.printRaw(t.getClass().getName() + ": " + t.getMessage());
editSession.enableQueue(); t.printStackTrace();
} catch (CommandException e) {
session.tellVersion(player); player.printError(e.getMessage());
} finally {
long start = System.currentTimeMillis(); EditSession editSession = locals.get(EditSession.class);
try { if (editSession != null) {
commands.execute(split, player, session, player, editSession); LocalSession session = getSession(player);
} catch (CommandPermissionsException e) {
player.printError("You don't have permission to do this.");
} catch (MissingNestedCommandException e) {
player.printError(e.getUsage());
} catch (CommandUsageException e) {
player.printError(e.getMessage());
player.printError(e.getUsage());
} catch (PlayerNeededException e) {
player.printError(e.getMessage());
} catch (WrappedCommandException e) {
throw e.getCause();
} catch (UnhandledCommandException e) {
player.printError("Command could not be handled; invalid sender!");
return false;
} finally {
session.remember(editSession); session.remember(editSession);
editSession.flushQueue(); editSession.flushQueue();
@ -1427,50 +1332,6 @@ public class WorldEdit {
flushBlockBag(player, editSession); flushBlockBag(player, editSession);
} }
} catch (NumberFormatException e) {
final Matcher matcher = numberFormatExceptionPattern.matcher(e.getMessage());
if (matcher.matches()) {
player.printError("Number expected; string \"" + matcher.group(1) + "\" given.");
} else {
player.printError("Number expected; string given.");
}
} catch (IncompleteRegionException e) {
player.printError("Make a region selection first.");
} catch (UnknownItemException e) {
player.printError("Block name '" + e.getID() + "' was not recognized.");
} catch (InvalidItemException e) {
player.printError(e.getMessage());
} catch (DisallowedItemException e) {
player.printError("Block '" + e.getID() + "' not allowed (see WorldEdit configuration).");
} catch (MaxChangedBlocksException e) {
player.printError("Max blocks changed in an operation reached ("
+ e.getBlockLimit() + ").");
} catch (MaxRadiusException e) {
player.printError("Maximum radius: " + config.maxRadius);
} catch (UnknownDirectionException e) {
player.printError("Unknown direction: " + e.getDirection());
} catch (InsufficientArgumentsException e) {
player.printError(e.getMessage());
} catch (EmptyClipboardException e) {
player.printError("Your clipboard is empty. Use //copy first.");
} catch (InvalidFilenameException e) {
player.printError("Filename '" + e.getFilename() + "' invalid: "
+ e.getMessage());
} catch (FilenameResolutionException e) {
player.printError("File '" + e.getFilename() + "' resolution error: "
+ e.getMessage());
} catch (InvalidToolBindException e) {
player.printError("Can't bind tool to "
+ ItemType.toHeldName(e.getItemId()) + ": " + e.getMessage());
} catch (FileSelectionAbortedException e) {
player.printError("File selection aborted.");
} catch (WorldEditException e) {
player.printError(e.getMessage());
} catch (Throwable excp) {
player.printError("Please report this error: [See console]");
player.printRaw(excp.getClass().getName() + ": " + excp.getMessage());
excp.printStackTrace();
} }
return true; return true;
@ -1491,11 +1352,11 @@ public class WorldEdit {
String searchCmd = split[0].toLowerCase(); String searchCmd = split[0].toLowerCase();
// Try to detect the command // Try to detect the command
if (commands.hasCommand(searchCmd)) { if (dispatcher.contains(searchCmd)) {
} else if (config.noDoubleSlash && commands.hasCommand("/" + searchCmd)) { } else if (config.noDoubleSlash && dispatcher.contains("/" + searchCmd)) {
split[0] = "/" + split[0]; split[0] = "/" + split[0];
} else if (split[0].length() >= 2 && split[0].charAt(0) == '/' } else if (split[0].length() >= 2 && split[0].charAt(0) == '/'
&& commands.hasCommand(searchCmd.substring(1))) { && dispatcher.contains(searchCmd.substring(1))) {
split[0] = split[0].substring(1); split[0] = split[0].substring(1);
} }
return split; return split;
@ -1599,6 +1460,15 @@ public class WorldEdit {
return config; return config;
} }
/**
* Get the command logger.
*
* @return the logger
*/
public CommandLoggingHandler getCommandLogger() {
return commandLogger;
}
/** /**
* Get the server interface. * Get the server interface.
* *

View File

@ -0,0 +1,37 @@
// $Id$
/*
* This file is a part of WorldEdit.
* Copyright (c) sk89q <http://www.sk89q.com>
* Copyright (c) the WorldEdit 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
* (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
* GNU 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.worldedit.annotation;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
import com.sk89q.worldedit.Vector;
/**
* Annotates a {@link Vector} parameter to inject a direction.
*/
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.PARAMETER)
public @interface Direction {
public static final String AIM = "me";
}

View File

@ -0,0 +1,33 @@
// $Id$
/*
* This file is a part of WorldEdit.
* Copyright (c) sk89q <http://www.sk89q.com>
* Copyright (c) the WorldEdit 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
* (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
* GNU 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.worldedit.annotation;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
/**
* Indicates that this value should come from the current selection.
*/
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.PARAMETER)
public @interface Selection {
}

View File

@ -23,20 +23,22 @@ import java.lang.reflect.Method;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.List; import java.util.List;
import com.sk89q.bukkit.util.CommandInfo;
import com.sk89q.bukkit.util.CommandRegistration;
import com.sk89q.minecraft.util.commands.Command;
import com.sk89q.minecraft.util.commands.CommandPermissions;
import com.sk89q.minecraft.util.commands.CommandsManager;
import com.sk89q.worldedit.LocalPlayer;
import org.bukkit.Bukkit; import org.bukkit.Bukkit;
import org.bukkit.Material; import org.bukkit.Material;
import org.bukkit.Server; import org.bukkit.Server;
import org.bukkit.World; import org.bukkit.World;
import org.bukkit.entity.EntityType; import org.bukkit.entity.EntityType;
import com.sk89q.bukkit.util.CommandInfo;
import com.sk89q.bukkit.util.CommandRegistration;
import com.sk89q.minecraft.util.commands.Command;
import com.sk89q.minecraft.util.commands.CommandPermissions;
import com.sk89q.minecraft.util.commands.CommandsManager;
import com.sk89q.rebar.command.CommandMapping;
import com.sk89q.rebar.command.Description;
import com.sk89q.rebar.command.Dispatcher;
import com.sk89q.worldedit.BiomeTypes; import com.sk89q.worldedit.BiomeTypes;
import com.sk89q.worldedit.LocalPlayer;
import com.sk89q.worldedit.LocalWorld; import com.sk89q.worldedit.LocalWorld;
import com.sk89q.worldedit.ServerInterface; import com.sk89q.worldedit.ServerInterface;
@ -108,6 +110,23 @@ public class BukkitServerInterface extends ServerInterface {
dynamicCommands.register(toRegister); dynamicCommands.register(toRegister);
} }
@Override
public void registerCommands(Dispatcher dispatcher) {
List<CommandInfo> toRegister = new ArrayList<CommandInfo>();
for (CommandMapping command : dispatcher.getCommands()) {
Description description = command.getDescription();
List<String> permissions = description.getPermissions();
String[] permissionsArray = new String[permissions.size()];
permissions.toArray(permissionsArray);
toRegister.add(new CommandInfo(
description.getUsage(), description.getDescription(),
command.getAllAliases(), dispatcher, permissionsArray));
}
dynamicCommands.register(toRegister);
}
public void unregisterCommands() { public void unregisterCommands() {
dynamicCommands.unregisterCommands(); dynamicCommands.unregisterCommands();
} }

View File

@ -27,7 +27,6 @@ import java.io.InputStream;
import java.util.Enumeration; import java.util.Enumeration;
import java.util.jar.JarEntry; import java.util.jar.JarEntry;
import java.util.jar.JarFile; import java.util.jar.JarFile;
import java.util.logging.Handler;
import java.util.zip.ZipEntry; import java.util.zip.ZipEntry;
import org.bukkit.Bukkit; import org.bukkit.Bukkit;
@ -61,32 +60,13 @@ import com.sk89q.worldedit.regions.RegionSelector;
*/ */
public class WorldEditPlugin extends JavaPlugin { public class WorldEditPlugin extends JavaPlugin {
/**
* The name of the CUI's plugin channel registration
*/
public static final String CUI_PLUGIN_CHANNEL = "WECUI"; public static final String CUI_PLUGIN_CHANNEL = "WECUI";
/**
* The server interface that all server-related API goes through.
*/
private BukkitServerInterface server; private BukkitServerInterface server;
/**
* Main WorldEdit instance.
*/
private WorldEdit controller; private WorldEdit controller;
/**
* Deprecated API.
*/
private WorldEditAPI api; private WorldEditAPI api;
/**
* Holds the configuration for WorldEdit.
*/
private BukkitConfiguration config; private BukkitConfiguration config;
/**
* Called on plugin enable.
*/
@Override @Override
public void onEnable() { public void onEnable() {
final String pluginYmlVersion = getDescription().getVersion(); final String pluginYmlVersion = getDescription().getVersion();
@ -165,9 +145,7 @@ public class WorldEditPlugin extends JavaPlugin {
} }
} }
controller.clearSessions(); controller.clearSessions();
for (Handler h : controller.commandLogger.getHandlers()) { controller.getCommandLogger().close();
h.close();
}
config.unload(); config.unload();
server.unregisterCommands(); server.unregisterCommands();
this.getServer().getScheduler().cancelTasks(this); this.getServer().getScheduler().cancelTasks(this);

View File

@ -1,6 +1,6 @@
package com.sk89q.worldedit.commands; package com.sk89q.worldedit.commands;
import static com.sk89q.minecraft.util.commands.Logging.LogMode.REGION; import static com.sk89q.minecraft.util.commands.Logging.LogMode.*;
import java.util.HashSet; import java.util.HashSet;
import java.util.List; import java.util.List;

View File

@ -19,14 +19,21 @@
package com.sk89q.worldedit.commands; package com.sk89q.worldedit.commands;
import static com.sk89q.minecraft.util.commands.Logging.LogMode.*;
import com.sk89q.minecraft.util.commands.Command; import com.sk89q.minecraft.util.commands.Command;
import com.sk89q.minecraft.util.commands.CommandContext; import com.sk89q.minecraft.util.commands.CommandContext;
import com.sk89q.minecraft.util.commands.CommandPermissions; import com.sk89q.minecraft.util.commands.CommandPermissions;
import com.sk89q.minecraft.util.commands.Logging; import com.sk89q.minecraft.util.commands.Logging;
import static com.sk89q.minecraft.util.commands.Logging.LogMode.*; import com.sk89q.worldedit.CuboidClipboard;
import com.sk89q.worldedit.EditSession;
import com.sk89q.minecraft.util.commands.NestedCommand; import com.sk89q.worldedit.LocalEntity;
import com.sk89q.worldedit.*; import com.sk89q.worldedit.LocalPlayer;
import com.sk89q.worldedit.LocalSession;
import com.sk89q.worldedit.LocalWorld;
import com.sk89q.worldedit.Vector;
import com.sk89q.worldedit.WorldEdit;
import com.sk89q.worldedit.WorldEditException;
import com.sk89q.worldedit.blocks.BaseBlock; import com.sk89q.worldedit.blocks.BaseBlock;
import com.sk89q.worldedit.blocks.BlockID; import com.sk89q.worldedit.blocks.BlockID;
import com.sk89q.worldedit.regions.Region; import com.sk89q.worldedit.regions.Region;
@ -232,13 +239,6 @@ public class ClipboardCommands {
player.printError("This command is no longer used. See //schematic save."); player.printError("This command is no longer used. See //schematic save.");
} }
@Command(
aliases = { "/schematic", "/schem"},
desc = "Schematic-related commands"
)
@NestedCommand(SchematicCommands.class)
public void schematic() {}
@Command( @Command(
aliases = { "clearclipboard" }, aliases = { "clearclipboard" },
usage = "", usage = "",

View File

@ -23,7 +23,6 @@ import com.sk89q.minecraft.util.commands.Command;
import com.sk89q.minecraft.util.commands.CommandContext; import com.sk89q.minecraft.util.commands.CommandContext;
import com.sk89q.minecraft.util.commands.CommandPermissions; import com.sk89q.minecraft.util.commands.CommandPermissions;
import com.sk89q.minecraft.util.commands.Console; import com.sk89q.minecraft.util.commands.Console;
import com.sk89q.minecraft.util.commands.NestedCommand;
import com.sk89q.worldedit.EditSession; import com.sk89q.worldedit.EditSession;
import com.sk89q.worldedit.LocalConfiguration; import com.sk89q.worldedit.LocalConfiguration;
import com.sk89q.worldedit.LocalPlayer; import com.sk89q.worldedit.LocalPlayer;
@ -221,14 +220,5 @@ public class GeneralCommands {
player.printError("No items found."); player.printError("No items found.");
} }
} }
@Command(
aliases = { "we", "worldedit" },
desc = "WorldEdit commands"
)
@NestedCommand(WorldEditCommands.class)
@Console
public void we(CommandContext args, LocalSession session, LocalPlayer player,
EditSession editSession) throws WorldEditException {
}
} }

View File

@ -19,7 +19,7 @@
package com.sk89q.worldedit.commands; package com.sk89q.worldedit.commands;
import static com.sk89q.minecraft.util.commands.Logging.LogMode.REGION; import static com.sk89q.minecraft.util.commands.Logging.LogMode.*;
import java.io.File; import java.io.File;
import java.io.IOException; import java.io.IOException;
@ -29,7 +29,6 @@ import com.sk89q.minecraft.util.commands.Command;
import com.sk89q.minecraft.util.commands.CommandContext; import com.sk89q.minecraft.util.commands.CommandContext;
import com.sk89q.minecraft.util.commands.CommandPermissions; import com.sk89q.minecraft.util.commands.CommandPermissions;
import com.sk89q.minecraft.util.commands.Logging; import com.sk89q.minecraft.util.commands.Logging;
import com.sk89q.minecraft.util.commands.NestedCommand;
import com.sk89q.worldedit.EditSession; import com.sk89q.worldedit.EditSession;
import com.sk89q.worldedit.LocalConfiguration; import com.sk89q.worldedit.LocalConfiguration;
import com.sk89q.worldedit.LocalPlayer; import com.sk89q.worldedit.LocalPlayer;
@ -54,15 +53,6 @@ public class SnapshotUtilCommands {
this.we = we; this.we = we;
} }
@Command(
aliases = { "snapshot", "snap" },
desc = "Snapshot commands"
)
@NestedCommand(SnapshotCommands.class)
public void snapshot(CommandContext args, LocalSession session, LocalPlayer player,
EditSession editSession) throws WorldEditException {
}
@Command( @Command(
aliases = { "restore", "/restore" }, aliases = { "restore", "/restore" },
usage = "[snapshot]", usage = "[snapshot]",

View File

@ -22,12 +22,23 @@ package com.sk89q.worldedit.commands;
import com.sk89q.minecraft.util.commands.Command; import com.sk89q.minecraft.util.commands.Command;
import com.sk89q.minecraft.util.commands.CommandContext; import com.sk89q.minecraft.util.commands.CommandContext;
import com.sk89q.minecraft.util.commands.CommandPermissions; import com.sk89q.minecraft.util.commands.CommandPermissions;
import com.sk89q.minecraft.util.commands.NestedCommand; import com.sk89q.worldedit.EditSession;
import com.sk89q.worldedit.*; import com.sk89q.worldedit.LocalConfiguration;
import com.sk89q.worldedit.LocalPlayer;
import com.sk89q.worldedit.LocalSession;
import com.sk89q.worldedit.WorldEdit;
import com.sk89q.worldedit.WorldEditException;
import com.sk89q.worldedit.blocks.BaseBlock; import com.sk89q.worldedit.blocks.BaseBlock;
import com.sk89q.worldedit.blocks.ItemType; import com.sk89q.worldedit.blocks.ItemType;
import com.sk89q.worldedit.patterns.Pattern; import com.sk89q.worldedit.patterns.Pattern;
import com.sk89q.worldedit.tools.*; import com.sk89q.worldedit.tools.BlockDataCyler;
import com.sk89q.worldedit.tools.BlockReplacer;
import com.sk89q.worldedit.tools.DistanceWand;
import com.sk89q.worldedit.tools.FloatingTreeRemover;
import com.sk89q.worldedit.tools.FloodFillTool;
import com.sk89q.worldedit.tools.LongRangeBuildTool;
import com.sk89q.worldedit.tools.QueryTool;
import com.sk89q.worldedit.tools.TreePlanter;
import com.sk89q.worldedit.util.TreeGenerator; import com.sk89q.worldedit.util.TreeGenerator;
public class ToolCommands { public class ToolCommands {
@ -151,15 +162,6 @@ public class ToolCommands {
+ ItemType.toHeldName(player.getItemInHand()) + "."); + ItemType.toHeldName(player.getItemInHand()) + ".");
} }
@Command(
aliases = { "brush", "br" },
desc = "Brush tool"
)
@NestedCommand(BrushCommands.class)
public void brush(CommandContext args, LocalSession session, LocalPlayer player,
EditSession editSession) throws WorldEditException {
}
@Command( @Command(
aliases = { "deltree" }, aliases = { "deltree" },
usage = "", usage = "",

View File

@ -22,8 +22,12 @@ package com.sk89q.worldedit.commands;
import com.sk89q.minecraft.util.commands.Command; import com.sk89q.minecraft.util.commands.Command;
import com.sk89q.minecraft.util.commands.CommandContext; import com.sk89q.minecraft.util.commands.CommandContext;
import com.sk89q.minecraft.util.commands.CommandPermissions; import com.sk89q.minecraft.util.commands.CommandPermissions;
import com.sk89q.minecraft.util.commands.NestedCommand; import com.sk89q.worldedit.EditSession;
import com.sk89q.worldedit.*; import com.sk89q.worldedit.LocalConfiguration;
import com.sk89q.worldedit.LocalPlayer;
import com.sk89q.worldedit.LocalSession;
import com.sk89q.worldedit.WorldEdit;
import com.sk89q.worldedit.WorldEditException;
import com.sk89q.worldedit.masks.Mask; import com.sk89q.worldedit.masks.Mask;
import com.sk89q.worldedit.patterns.Pattern; import com.sk89q.worldedit.patterns.Pattern;
@ -70,24 +74,6 @@ public class ToolUtilCommands {
} }
@Command(
aliases = { "superpickaxe", "pickaxe", "sp" },
desc = "Select super pickaxe mode"
)
@NestedCommand(SuperPickaxeCommands.class)
public void pickaxe(CommandContext args, LocalSession session, LocalPlayer player,
EditSession editSession) throws WorldEditException {
}
@Command(
aliases = {"tool"},
desc = "Select a tool to bind"
)
@NestedCommand(ToolCommands.class)
public void tool(CommandContext args, LocalSession session, LocalPlayer player,
EditSession editSession) throws WorldEditException {
}
@Command( @Command(
aliases = { "mask" }, aliases = { "mask" },
usage = "[mask]", usage = "[mask]",

View File

@ -19,9 +19,11 @@
package com.sk89q.worldedit.commands; package com.sk89q.worldedit.commands;
import static com.sk89q.minecraft.util.commands.Logging.LogMode.PLACEMENT; import static com.sk89q.minecraft.util.commands.Logging.LogMode.*;
import java.util.ArrayList;
import java.util.Comparator; import java.util.Comparator;
import java.util.List;
import java.util.Set; import java.util.Set;
import java.util.SortedSet; import java.util.SortedSet;
import java.util.TreeSet; import java.util.TreeSet;
@ -29,9 +31,11 @@ import java.util.TreeSet;
import com.sk89q.minecraft.util.commands.Command; import com.sk89q.minecraft.util.commands.Command;
import com.sk89q.minecraft.util.commands.CommandContext; import com.sk89q.minecraft.util.commands.CommandContext;
import com.sk89q.minecraft.util.commands.CommandPermissions; import com.sk89q.minecraft.util.commands.CommandPermissions;
import com.sk89q.minecraft.util.commands.CommandsManager;
import com.sk89q.minecraft.util.commands.Console; import com.sk89q.minecraft.util.commands.Console;
import com.sk89q.minecraft.util.commands.Logging; import com.sk89q.minecraft.util.commands.Logging;
import com.sk89q.rebar.command.CommandMapping;
import com.sk89q.rebar.command.Description;
import com.sk89q.rebar.command.Dispatcher;
import com.sk89q.worldedit.EditSession; import com.sk89q.worldedit.EditSession;
import com.sk89q.worldedit.EntityType; import com.sk89q.worldedit.EntityType;
import com.sk89q.worldedit.LocalConfiguration; import com.sk89q.worldedit.LocalConfiguration;
@ -520,7 +524,7 @@ public class UtilityCommands {
} }
public static void help(CommandContext args, WorldEdit we, LocalSession session, LocalPlayer player, EditSession editSession) { public static void help(CommandContext args, WorldEdit we, LocalSession session, LocalPlayer player, EditSession editSession) {
final CommandsManager<LocalPlayer> commandsManager = we.getCommandsManager(); Dispatcher dispatcher = we.getDispatcher();
if (args.argsLength() == 0) { if (args.argsLength() == 0) {
SortedSet<String> commands = new TreeSet<String>(new Comparator<String>() { SortedSet<String> commands = new TreeSet<String>(new Comparator<String>() {
@ -533,7 +537,7 @@ public class UtilityCommands {
return ret; return ret;
} }
}); });
commands.addAll(commandsManager.getCommands().keySet()); commands.addAll(dispatcher.getPrimaryAliases());
StringBuilder sb = new StringBuilder(); StringBuilder sb = new StringBuilder();
boolean first = true; boolean first = true;
@ -552,14 +556,58 @@ public class UtilityCommands {
return; return;
} }
String command = args.getJoinedStrings(0).replaceAll("/", ""); String command = args.getJoinedStrings(0);
String helpMessage = commandsManager.getHelpMessages().get(command); List<CommandMapping> mappings = new ArrayList<CommandMapping>();
if (helpMessage == null) {
String testCommand = command.replaceAll("/", "");
for (int i = 0; i < 3; i++) {
CommandMapping mapping = dispatcher.get(testCommand);
if (mapping != null) {
mappings.add(mapping);
}
testCommand = "/" + testCommand;
}
if (mappings.size() == 0) {
player.printError("Unknown command '" + command + "'."); player.printError("Unknown command '" + command + "'.");
return; return;
} }
player.print(helpMessage); StringBuilder builder = new StringBuilder("\n");
int index = 0;
for (CommandMapping mapping : mappings) {
if (index != 0) {
builder.append("\n");
}
if (mappings.size() > 1) {
builder.append("#").append(index + 1).append(". \n");
}
Description desc = mapping.getDescription();
builder.append("Aliases: ");
boolean first = true;
for (String alias : mapping.getAllAliases()) {
if (!first) {
builder.append(", ");
}
builder.append("/").append(alias);
first = false;
}
builder.append("\n");
builder.append("Usage: ").append(desc.getUsage()).append("\n");
if (desc.getHelp() != null) {
builder.append("Help: ").append(desc.getHelp()).append("\n");
} else if (desc.getDescription() != null) {
builder.append("Description: ").append(desc.getDescription()).append("\n");
}
index++;
}
player.print(builder.toString());
} }
} }

View File

@ -0,0 +1,164 @@
// $Id$
package com.sk89q.worldedit.util;
import java.io.Closeable;
import java.io.File;
import java.io.IOException;
import java.lang.reflect.Method;
import java.util.logging.FileHandler;
import java.util.logging.Handler;
import java.util.logging.Level;
import java.util.logging.Logger;
import com.sk89q.minecraft.util.commands.CommandContext;
import com.sk89q.minecraft.util.commands.CommandException;
import com.sk89q.minecraft.util.commands.Logging;
import com.sk89q.rebar.command.parametric.AbstractInvokeListener;
import com.sk89q.rebar.command.parametric.InvokeHandler;
import com.sk89q.rebar.command.parametric.ParameterData;
import com.sk89q.rebar.command.parametric.ParameterException;
import com.sk89q.worldedit.IncompleteRegionException;
import com.sk89q.worldedit.LocalConfiguration;
import com.sk89q.worldedit.LocalPlayer;
import com.sk89q.worldedit.LocalSession;
import com.sk89q.worldedit.LogFormat;
import com.sk89q.worldedit.Vector;
import com.sk89q.worldedit.WorldEdit;
/**
* Logs called commands to a file.
*/
public class CommandLoggingHandler
extends AbstractInvokeListener
implements InvokeHandler, Closeable {
private static final Logger logger =
Logger.getLogger(CommandLoggingHandler.class.getCanonicalName());
private final WorldEdit worldEdit;
private final LocalConfiguration config;
private final Logger commandLogger =
Logger.getLogger("Minecraft.WorldEdit.CommandLogger");
/**
* Create a new instance.
*
* @param worldEdit WorldEdit instance
* @param config the configuration
*/
public CommandLoggingHandler(WorldEdit worldEdit, LocalConfiguration config) {
this.worldEdit = worldEdit;
this.config = config;
if (!config.logFile.equals("")) {
try {
FileHandler logFileHandler;
File file = new File(config.getWorkingDirectory(), config.logFile);
logFileHandler = new FileHandler(file.getAbsolutePath(), true);
logFileHandler.setFormatter(new LogFormat());
commandLogger.addHandler(logFileHandler);
} catch (IOException e) {
logger.log(Level.WARNING, "Could not use command log file "
+ config.logFile + ": " + e.getMessage());
}
}
}
@Override
public void preProcess(Object object, Method method,
ParameterData[] parameters, CommandContext context)
throws CommandException, ParameterException {
}
@Override
public void preInvoke(Object object, Method method, ParameterData[] parameters,
Object[] args, CommandContext context) throws CommandException {
if (!config.logCommands) {
return;
}
Logging loggingAnnotation = method.getAnnotation(Logging.class);
Logging.LogMode logMode;
StringBuilder builder = new StringBuilder();
if (loggingAnnotation == null) {
logMode = null;
} else {
logMode = loggingAnnotation.value();
}
LocalPlayer sender = context.getLocals().get(LocalPlayer.class);
if (sender == null) {
return;
}
builder.append("WorldEdit: ").append(sender.getName());
if (sender.isPlayer()) {
builder.append(" (in \"" + sender.getWorld().getName() + "\")");
}
builder.append(": ").append(context.getCommand());
if (context.argsLength() > 0) {
builder.append(" ").append(context.getJoinedStrings(0));
}
if (logMode != null && sender.isPlayer()) {
Vector position = sender.getPosition();
LocalSession session = worldEdit.getSession(sender);
switch (logMode) {
case PLACEMENT:
try {
position = session.getPlacementPosition(sender);
} catch (IncompleteRegionException e) {
break;
}
/* FALL-THROUGH */
case POSITION:
builder.append(" - Position: " + position);
break;
case ALL:
builder.append(" - Position: " + position);
/* FALL-THROUGH */
case ORIENTATION_REGION:
builder.append(" - Orientation: "
+ sender.getCardinalDirection().name());
/* FALL-THROUGH */
case REGION:
try {
builder.append(" - Region: ")
.append(session.getSelection(sender.getWorld()));
} catch (IncompleteRegionException e) {
break;
}
break;
}
}
commandLogger.info(builder.toString());
}
@Override
public void postInvoke(Object object, Method method, ParameterData[] parameters,
Object[] args, CommandContext context) throws CommandException {
}
@Override
public InvokeHandler createInvokeHandler() {
return this;
}
@Override
public void close() {
for (Handler h : commandLogger.getHandlers()) {
h.close();
}
}
}

View File

@ -0,0 +1,40 @@
// $Id$
/*
* This file is a part of WorldEdit.
* Copyright (c) sk89q <http://www.sk89q.com>
* Copyright (c) the WorldEdit 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
* (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
* GNU 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.worldedit.util;
import com.sk89q.minecraft.util.commands.CommandContext;
import com.sk89q.rebar.command.parametric.PermissionsHandler;
import com.sk89q.worldedit.LocalPlayer;
public class CommandPermissionsHandler extends PermissionsHandler {
public CommandPermissionsHandler() {
}
@Override
protected boolean hasPermission(CommandContext context, String permission) {
LocalPlayer sender = context.getLocals().get(LocalPlayer.class);
if (sender == null) {
return true;
} else {
return sender.hasPermission(permission);
}
}
}

View File

@ -0,0 +1,177 @@
// $Id$
/*
* This file is a part of WorldEdit.
* Copyright (c) sk89q <http://www.sk89q.com>
* Copyright (c) the WorldEdit 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
* (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
* GNU 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.worldedit.util;
import com.sk89q.rebar.command.parametric.BindingBehavior;
import com.sk89q.rebar.command.parametric.BindingHelper;
import com.sk89q.rebar.command.parametric.BindingMatch;
import com.sk89q.rebar.command.parametric.ParameterException;
import com.sk89q.rebar.command.parametric.ArgumentStack;
import com.sk89q.worldedit.EditSession;
import com.sk89q.worldedit.IncompleteRegionException;
import com.sk89q.worldedit.LocalPlayer;
import com.sk89q.worldedit.LocalSession;
import com.sk89q.worldedit.UnknownDirectionException;
import com.sk89q.worldedit.Vector;
import com.sk89q.worldedit.WorldEdit;
import com.sk89q.worldedit.WorldEditException;
import com.sk89q.worldedit.annotation.Direction;
import com.sk89q.worldedit.annotation.Selection;
import com.sk89q.worldedit.masks.Mask;
import com.sk89q.worldedit.patterns.Pattern;
import com.sk89q.worldedit.regions.Region;
/**
* Binds standard WorldEdit classes such as {@link LocalPlayer} and {@link LocalSession}.
*/
public class WorldEditBinding extends BindingHelper {
private final WorldEdit worldEdit;
/**
* Create a new instance.
*
* @param worldEdit the WorldEdit instance to bind to
*/
public WorldEditBinding(WorldEdit worldEdit) {
this.worldEdit = worldEdit;
}
/**
* Gets a selection from a {@link ArgumentStack}.
*
* @param context the context
* @param selection the annotation
* @return a selection
* @throws IncompleteRegionException if no selection is available
* @throws ParameterException on other error
*/
@BindingMatch(classifier = Selection.class,
type = Region.class,
behavior = BindingBehavior.PROVIDES)
public Object getSelection(ArgumentStack context, Selection selection)
throws IncompleteRegionException, ParameterException {
LocalPlayer sender = getLocalPlayer(context);
LocalSession session = worldEdit.getSession(sender);
return session.getSelection(sender.getWorld());
}
/**
* Gets an {@link EditSession} from a {@link ArgumentStack}.
*
* @param context the context
* @return an edit session
* @throws ParameterException on other error
*/
@BindingMatch(type = EditSession.class,
behavior = BindingBehavior.PROVIDES)
public EditSession getEditSession(ArgumentStack context) throws ParameterException {
LocalPlayer sender = getLocalPlayer(context);
LocalSession session = worldEdit.getSession(sender);
EditSession editSession = session.createEditSession(sender);
editSession.enableQueue();
context.getContext().getLocals().put(EditSession.class, editSession);
session.tellVersion(sender);
return editSession;
}
/**
* Gets an {@link LocalSession} from a {@link ArgumentStack}.
*
* @param context the context
* @return a local session
* @throws ParameterException on error
*/
@BindingMatch(type = LocalSession.class,
behavior = BindingBehavior.PROVIDES)
public LocalSession getLocalSession(ArgumentStack context) throws ParameterException {
LocalPlayer sender = getLocalPlayer(context);
return worldEdit.getSession(sender);
}
/**
* Gets an {@link LocalPlayer} from a {@link ArgumentStack}.
*
* @param context the context
* @return a local player
* @throws ParameterException on error
*/
@BindingMatch(type = LocalPlayer.class,
behavior = BindingBehavior.PROVIDES)
public LocalPlayer getLocalPlayer(ArgumentStack context) throws ParameterException {
LocalPlayer sender = context.getContext().getLocals().get(LocalPlayer.class);
if (sender == null) {
throw new ParameterException("No player to get a session for");
}
return sender;
}
/**
* Gets an {@link Pattern} from a {@link ArgumentStack}.
*
* @param context the context
* @return a pattern
* @throws ParameterException on error
* @throws WorldEditException on error
*/
@BindingMatch(type = Pattern.class,
behavior = BindingBehavior.CONSUMES,
consumedCount = 1)
public Pattern getPattern(ArgumentStack context)
throws ParameterException, WorldEditException {
return worldEdit.getBlockPattern(getLocalPlayer(context), context.next());
}
/**
* Gets an {@link Mask} from a {@link ArgumentStack}.
*
* @param context the context
* @return a pattern
* @throws ParameterException on error
* @throws WorldEditException on error
*/
@BindingMatch(type = Mask.class,
behavior = BindingBehavior.CONSUMES,
consumedCount = 1)
public Mask getMask(ArgumentStack context)
throws ParameterException, WorldEditException {
return worldEdit.getBlockMask(getLocalPlayer(context),
getLocalSession(context), context.next());
}
/**
* Get a direction from the player.
*
* @param context the context
* @param direction the direction annotation
* @return a pattern
* @throws ParameterException on error
* @throws UnknownDirectionException on an unknown direction
*/
@BindingMatch(classifier = Direction.class,
type = Vector.class,
behavior = BindingBehavior.CONSUMES,
consumedCount = 1)
public Vector getDirection(ArgumentStack context, Direction direction)
throws ParameterException, UnknownDirectionException {
LocalPlayer sender = getLocalPlayer(context);
return worldEdit.getDirection(sender, context.next());
}
}

View File

@ -0,0 +1,163 @@
// $Id$
/*
* This file is a part of WorldEdit.
* Copyright (c) sk89q <http://www.sk89q.com>
* Copyright (c) the WorldEdit 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
* (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
* GNU 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.worldedit.util;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import com.sk89q.minecraft.util.commands.CommandException;
import com.sk89q.rebar.command.parametric.ExceptionConverterHelper;
import com.sk89q.rebar.command.parametric.ExceptionMatch;
import com.sk89q.worldedit.DisallowedItemException;
import com.sk89q.worldedit.EmptyClipboardException;
import com.sk89q.worldedit.FileSelectionAbortedException;
import com.sk89q.worldedit.FilenameResolutionException;
import com.sk89q.worldedit.IncompleteRegionException;
import com.sk89q.worldedit.InvalidFilenameException;
import com.sk89q.worldedit.InvalidItemException;
import com.sk89q.worldedit.InvalidToolBindException;
import com.sk89q.worldedit.LocalConfiguration;
import com.sk89q.worldedit.MaxChangedBlocksException;
import com.sk89q.worldedit.MaxRadiusException;
import com.sk89q.worldedit.PlayerNeededException;
import com.sk89q.worldedit.UnknownDirectionException;
import com.sk89q.worldedit.UnknownItemException;
import com.sk89q.worldedit.WorldEditException;
import com.sk89q.worldedit.blocks.ItemType;
import com.sk89q.worldedit.commands.InsufficientArgumentsException;
import com.sk89q.worldedit.expression.ExpressionException;
import com.sk89q.worldedit.regions.RegionOperationException;
/**
* converts WorldEdit exceptions and converts them into {@link CommandException}s.
*/
public class WorldEditExceptionConverter extends ExceptionConverterHelper {
private static final Pattern numberFormat = Pattern
.compile("^For input string: \"(.*)\"$");
private final LocalConfiguration config;
public WorldEditExceptionConverter(LocalConfiguration config) {
this.config = config;
}
@ExceptionMatch
public void convert(PlayerNeededException e) throws CommandException {
throw new CommandException(e.getMessage());
}
@ExceptionMatch
public void convert(NumberFormatException e) throws CommandException {
final Matcher matcher = numberFormat.matcher(e.getMessage());
if (matcher.matches()) {
throw new CommandException("Number expected; string \"" + matcher.group(1)
+ "\" given.");
} else {
throw new CommandException("Number expected; string given.");
}
}
@ExceptionMatch
public void convert(IncompleteRegionException e) throws CommandException {
throw new CommandException("Make a region selection first.");
}
@ExceptionMatch
public void convert(UnknownItemException e) throws CommandException {
throw new CommandException("Block name '" + e.getID() + "' was not recognized.");
}
@ExceptionMatch
public void convert(InvalidItemException e) throws CommandException {
throw new CommandException(e.getMessage());
}
@ExceptionMatch
public void convert(DisallowedItemException e) throws CommandException {
throw new CommandException("Block '" + e.getID()
+ "' not allowed (see WorldEdit configuration).");
}
@ExceptionMatch
public void convert(MaxChangedBlocksException e) throws CommandException {
throw new CommandException("Max blocks changed in an operation reached ("
+ e.getBlockLimit() + ").");
}
@ExceptionMatch
public void convert(MaxRadiusException e) throws CommandException {
throw new CommandException("Maximum radius: " + config.maxRadius);
}
@ExceptionMatch
public void convert(UnknownDirectionException e) throws CommandException {
throw new CommandException("Unknown direction: " + e.getDirection());
}
@ExceptionMatch
public void convert(InsufficientArgumentsException e) throws CommandException {
throw new CommandException(e.getMessage());
}
@ExceptionMatch
public void convert(RegionOperationException e) throws CommandException {
throw new CommandException(e.getMessage());
}
@ExceptionMatch
public void convert(ExpressionException e) throws CommandException {
throw new CommandException(e.getMessage());
}
@ExceptionMatch
public void convert(EmptyClipboardException e) throws CommandException {
throw new CommandException("Your clipboard is empty. Use //copy first.");
}
@ExceptionMatch
public void convert(InvalidFilenameException e) throws CommandException {
throw new CommandException("Filename '" + e.getFilename() + "' invalid: "
+ e.getMessage());
}
@ExceptionMatch
public void convert(FilenameResolutionException e) throws CommandException {
throw new CommandException(
"File '" + e.getFilename() + "' resolution error: " + e.getMessage());
}
@ExceptionMatch
public void convert(InvalidToolBindException e) throws CommandException {
throw new CommandException("Can't bind tool to "
+ ItemType.toHeldName(e.getItemId()) + ": " + e.getMessage());
}
@ExceptionMatch
public void convert(FileSelectionAbortedException e) throws CommandException {
throw new CommandException("File selection aborted.");
}
@ExceptionMatch
public void convert(WorldEditException e) throws CommandException {
throw new CommandException(e.getMessage());
}
}