sk89q/worldedit — pull request #250 by sk89q (2013-06-22 08:45:51+00:00)
Title: Operations API and performing operations in batches

OK, this is definitely not anywhere done, but I've added the old operations API from the other branches into `operations`, and it works. Right now, if you do `//set`, the blocks are placed *in batches without freezing the server*.

This branch is based off of `new-commands`.

API summary
--------------

An operation performs a task, such as placing blocks.

```java
public interface Operation {
Operation resume(ExecutionHint opt) throws WorldEditException;
void cancel();
}
```

Operations can return themselves to imply that they must be called again, or they can return null to signify that they are done. When `resume()` is called, a hint is provided to tell the operation how much it should do.

```java
public interface ExecutionHint {
boolean preferSingleRun();
int getBlockCount();
}
```

Operation executors are used to schedule operators.

```java
public interface OperationExecutor extends Runnable {
ListenableFuture offer(Operation operation)
throws RejectedOperationException;
boolean resume();
}
```

A returned `ListenableFuture` can have a callback added to it, which will be called on success or error.

**Note:** I am using the concurrency classes from Guava because Java's lacks the required classes.

Executing an operation is easy. The code for `//set` is now simply:

```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, @Unmanaged EditSession editSession,
@Selection Region region, Pattern replaceWith)
throws WorldEditException, RejectedOperationException {
ReplaceBlocks op = new ReplaceBlocks(editSession, region, replaceWith);
worldEdit.execute(player, op, editSession);
}
```

Operation classes
--------------

There is now significantly reduced repetitive code. For example, `//thaw`, which visits blocks in a flat region that covers the selected region, works similarly to how `//forestgen` works. The two can now share a class that knows how to visit "columns" of blocks.

```java
public class ThawArea extends ColumnVisitor implements ChangeCountable {
// ...
}
```

Then the column visitor:

```java
public abstract class ColumnVisitor implements Operation {
// ...
}
```

This saves a bit of code.

Status
--------------

OK, there's still quite a bit to be done:

* The ability to cancel operations as they are in progress.
* Telling the user that his/her operation was queued.
* The option to adjust the execution rate.
* Converting everything over to the new system.
* Using a two-pass system where physics are not called until afterwards.

Any comments/opinions on the API? The branch is currently usable -- `//set` will set blocks in small batches.