sk89q/worldedit — pull request #248 by sk89q (2013-06-18 22:29:39+00:00)
Title: Parameter injection for commands

This adds support for parameter injection with commands.

I don't actually want to merge right away because I want to test a bit more, but I'd like some input (and any objections).

Old vs. new
---------

```java
@Command(
aliases = { "/set" },
usage = "",
desc = "Set all the blocks inside the selection to a block",
min = 1,
max = 1
)
@CommandPermissions("worldedit.region.set")
@Logging(REGION)
public void set(CommandContext args, LocalSession session, LocalPlayer player,
EditSession editSession) throws WorldEditException {

Pattern pattern = we.getBlockPattern(player, args.getString(0));

int affected;

if (pattern instanceof SingleBlockPattern) {
affected = editSession.setBlocks(session.getSelection(player.getWorld()),
((SingleBlockPattern) pattern).getBlock());
} else {
affected = editSession.setBlocks(session.getSelection(player.getWorld()), pattern);
}

player.print(affected + " block(s) have been changed.");
}
```

becomes a more manageable

```java
@Command(aliases = "/set",
desc = "Set all the blocks inside the selection to a block")
@CommandPermissions("worldedit.region.set")
@Logging(REGION)
public void setBlocks(LocalPlayer player, EditSession editSession,
@Selection Region region, Pattern replaceWith)
throws MaxChangedBlocksException {

int affected = editSession.setBlocks(region, replaceWith);
player.print(affected + " block(s) have been changed.");
}
```

Bindings
---------

Adding support for a new type of parameter is easy.

```java
@BindingMatch(type = Pattern.class,
behavior = BindingBehavior.CONSUMES,
consumedCount = 1)
public Pattern getPattern(ArgumentStack context)
throws ParameterException, WorldEditException {
return worldEdit.getBlockPattern(getLocalPlayer(context), context.next());
}
```

Exception handling
---------

Previously, non-command related exceptions were handled in an ugly big try-catch that couldn't be 'reused' anywhere else. Now it's stored off in a reusuable class.

```java
@ExceptionMatch
public void convert(IncompleteRegionException e) throws CommandException {
throw new CommandException("Make a region selection first.");
}
```

Special behavior
---------

WorldEdit has its an annotation logging mechanism, and this was handled by overriding the method performing the invoke() call. Now it's much cleaner, and you can mix and match modules.

```java
builder.attach(new CommandPermissionsHandler());
builder.attach(new WorldEditExceptionConverter(config));
builder.attach(new LegacyCommandsHandler());
builder.attach(commandLogger = new CommandLoggingHandler(this, config));
```

Better responses
---------

Before, we had to define `usage = "var1 var2 [var3]" by hand, but that was annoying and it could become out of date if command changed but the annotation wasn't. Now the new command builder generates these usage strings automatically and uses the names of the parameters (in the source code) to fill in parameter names.

It also provides generally better responses if you type too many arguments or too few.