Merge commit '142f5c8e5c889ee5098c05ba2fde20b52467c1df' into feature/platform-caps

This commit is contained in:
sk89q
2014-06-27 16:03:29 -07:00
69 changed files with 5209 additions and 359 deletions

View File

@ -42,15 +42,4 @@ public abstract class AbstractPlatform implements Platform {
return Collections.emptyList();
}
@Override
@Deprecated
public void onCommandRegistration(List<Command> commands) {
// Do nothing :)
}
@Override
public void onCommandRegistration(List<Command> commands, CommandsManager<LocalPlayer> manager) {
onCommandRegistration(commands);
}
}

View File

@ -19,22 +19,35 @@
package com.sk89q.worldedit.extension.platform;
import com.sk89q.minecraft.util.commands.*;
import com.sk89q.util.StringUtil;
import com.sk89q.worldedit.*;
import com.sk89q.worldedit.blocks.ItemType;
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.WrappedCommandException;
import com.sk89q.worldedit.EditSession;
import com.sk89q.worldedit.LocalConfiguration;
import com.sk89q.worldedit.LocalSession;
import com.sk89q.worldedit.WorldEdit;
import com.sk89q.worldedit.command.*;
import com.sk89q.worldedit.event.platform.CommandEvent;
import com.sk89q.worldedit.session.request.Request;
import com.sk89q.worldedit.util.logging.LogFormat;
import com.sk89q.worldedit.util.CommandLoggingHandler;
import com.sk89q.worldedit.util.CommandPermissionsHandler;
import com.sk89q.worldedit.util.WorldEditBinding;
import com.sk89q.worldedit.util.WorldEditExceptionConverter;
import com.sk89q.worldedit.util.command.Dispatcher;
import com.sk89q.worldedit.util.command.InvalidUsageException;
import com.sk89q.worldedit.util.command.fluent.CommandGraph;
import com.sk89q.worldedit.util.command.parametric.LegacyCommandsHandler;
import com.sk89q.worldedit.util.command.parametric.ParametricBuilder;
import com.sk89q.worldedit.util.eventbus.Subscribe;
import com.sk89q.worldedit.util.logging.DynamicStreamHandler;
import com.sk89q.worldedit.util.logging.LogFormat;
import java.io.File;
import java.io.IOException;
import java.lang.reflect.Method;
import java.util.logging.*;
import java.util.regex.Matcher;
import java.util.logging.FileHandler;
import java.util.logging.Level;
import java.util.logging.Logger;
import static com.google.common.base.Preconditions.checkNotNull;
@ -49,7 +62,7 @@ public final class CommandManager {
private static final java.util.regex.Pattern numberFormatExceptionPattern = java.util.regex.Pattern.compile("^For input string: \"(.*)\"$");
private final WorldEdit worldEdit;
private final CommandsManager<LocalPlayer> commands;
private final Dispatcher dispatcher;
private final DynamicStreamHandler dynamicHandler = new DynamicStreamHandler();
/**
@ -69,8 +82,56 @@ public final class CommandManager {
dynamicHandler.setFormatter(new LogFormat());
// Set up the commands manager
commands = new CommandsManagerImpl();
commands.setInjector(new SimpleInjector(worldEdit));
ParametricBuilder builder = new ParametricBuilder();
builder.addBinding(new WorldEditBinding(worldEdit));
builder.attach(new CommandPermissionsHandler());
builder.attach(new WorldEditExceptionConverter(worldEdit));
builder.attach(new LegacyCommandsHandler());
builder.attach(new CommandLoggingHandler(worldEdit, logger));
dispatcher = new CommandGraph()
.builder(builder)
.commands()
.build(new BiomeCommands(worldEdit))
.build(new ChunkCommands(worldEdit))
.build(new ClipboardCommands(worldEdit))
.build(new GeneralCommands(worldEdit))
.build(new GenerationCommands(worldEdit))
.build(new HistoryCommands(worldEdit))
.build(new NavigationCommands(worldEdit))
.build(new RegionCommands(worldEdit))
.build(new ScriptingCommands(worldEdit))
.build(new SelectionCommands(worldEdit))
.build(new SnapshotUtilCommands(worldEdit))
.build(new ToolUtilCommands(worldEdit))
.build(new ToolCommands(worldEdit))
.build(new UtilityCommands(worldEdit))
.group("worldedit", "we")
.describe("WorldEdit commands")
.build(new WorldEditCommands(worldEdit))
.parent()
.group("schematic", "schem", "/schematic", "/schem")
.describe("Schematic commands for saving/loading areas")
.build(new SchematicCommands(worldEdit))
.parent()
.group("snapshot", "snap")
.describe("Schematic commands for saving/loading areas")
.build(new SnapshotCommands(worldEdit))
.parent()
.group("brush", "br")
.describe("Brushing commands")
.build(new BrushCommands(worldEdit))
.parent()
.group("superpickaxe", "pickaxe", "sp")
.describe("Super-pickaxe commands")
.build(new SuperPickaxeCommands(worldEdit))
.parent()
.group("tool")
.describe("Bind functions to held items")
.build(new ToolCommands(worldEdit))
.parent()
.graph()
.getDispatcher();
}
void register(Platform platform) {
@ -95,37 +156,14 @@ public final class CommandManager {
}
}
register(platform, BiomeCommands.class);
register(platform, ChunkCommands.class);
register(platform, ClipboardCommands.class);
register(platform, GeneralCommands.class);
register(platform, GenerationCommands.class);
register(platform, HistoryCommands.class);
register(platform, NavigationCommands.class);
register(platform, RegionCommands.class);
register(platform, ScriptingCommands.class);
register(platform, SelectionCommands.class);
register(platform, SnapshotUtilCommands.class);
register(platform, ToolUtilCommands.class);
register(platform, ToolCommands.class);
register(platform, UtilityCommands.class);
platform.registerCommands(dispatcher);
}
void unregister() {
dynamicHandler.setHandler(null);
}
private void register(Platform platform, Class<?> clazz) {
platform.onCommandRegistration(commands.registerAndReturn(clazz), commands);
}
public CommandsManager<LocalPlayer> getCommands() {
return commands;
}
public String[] commandDetection(String[] split) {
Request.reset();
split[0] = split[0].substring(1);
// Quick script shortcut
@ -140,14 +178,13 @@ public final class CommandManager {
String searchCmd = split[0].toLowerCase();
// Try to detect the command
if (commands.hasCommand(searchCmd)) {
} else if (worldEdit.getConfiguration().noDoubleSlash && commands.hasCommand("/" + searchCmd)) {
if (dispatcher.contains(searchCmd)) {
} else if (worldEdit.getConfiguration().noDoubleSlash && dispatcher.contains("/" + searchCmd)) {
split[0] = "/" + split[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);
}
return split;
}
@ -155,185 +192,69 @@ public final class CommandManager {
public void handleCommand(CommandEvent event) {
Request.reset();
LocalPlayer player = event.getPlayer();
String[] split = event.getArguments();
Actor actor = event.getPlayer();
String split[] = commandDetection(event.getArguments());
// No command found!
if (!dispatcher.contains(split[0])) {
return;
}
LocalSession session = worldEdit.getSessionManager().get(actor);
LocalConfiguration config = worldEdit.getConfiguration();
CommandLocals locals = new CommandLocals();
locals.put(Actor.class, actor);
long start = System.currentTimeMillis();
try {
split = commandDetection(split);
dispatcher.call(split, locals);
} catch (CommandPermissionsException e) {
actor.printError("You don't have permission to do this.");
} catch (InvalidUsageException e) {
actor.printError(e.getMessage() + "\nUsage: " + e.getUsage("/"));
} catch (WrappedCommandException e) {
Throwable t = e.getCause();
actor.printError("Please report this error: [See console]");
actor.printRaw(t.getClass().getName() + ": " + t.getMessage());
t.printStackTrace();
} catch (CommandException e) {
actor.printError(e.getMessage());
} finally {
EditSession editSession = locals.get(EditSession.class);
// No command found!
if (!commands.hasCommand(split[0])) {
return;
}
LocalSession session = worldEdit.getSession(player);
EditSession editSession = session.createEditSession(player);
editSession.enableQueue();
session.tellVersion(player);
long start = System.currentTimeMillis();
try {
commands.execute(split, player, session, player, editSession);
} 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!");
event.setCancelled(true);
return;
} finally {
if (editSession != null) {
session.remember(editSession);
editSession.flushQueue();
if (worldEdit.getConfiguration().profile) {
if (config.profile) {
long time = System.currentTimeMillis() - start;
int changed = editSession.getBlockChangeCount();
if (time > 0) {
double throughput = changed / (time / 1000.0);
player.printDebug((time / 1000.0) + "s elapsed (history: "
actor.printDebug((time / 1000.0) + "s elapsed (history: "
+ changed + " changed; "
+ Math.round(throughput) + " blocks/sec).");
} else {
player.printDebug((time / 1000.0) + "s elapsed.");
actor.printDebug((time / 1000.0) + "s elapsed.");
}
}
worldEdit.flushBlockBag(player, editSession);
worldEdit.flushBlockBag(event.getPlayer(), 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 (MaxBrushRadiusException e) {
player.printError("Maximum allowed brush size: " + worldEdit.getConfiguration().maxBrushRadius);
} catch (MaxRadiusException e) {
player.printError("Maximum allowed size: " + worldEdit.getConfiguration().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();
}
event.setCancelled(true);
}
private class CommandsManagerImpl extends 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 (worldEdit.getConfiguration().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 = worldEdit.getSessionManager().get(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;
}
}
getLogger().info(msg);
}
super.invokeMethod(parent, args, player, method, instance, methodArgs, level);
}
/**
* Get the command dispatcher instance.
*
* @return the command dispatcher
*/
public Dispatcher getDispatcher() {
return dispatcher;
}
public static Logger getLogger() {

View File

@ -19,12 +19,10 @@
package com.sk89q.worldedit.extension.platform;
import com.sk89q.minecraft.util.commands.Command;
import com.sk89q.minecraft.util.commands.CommandsManager;
import com.sk89q.worldedit.BiomeTypes;
import com.sk89q.worldedit.LocalConfiguration;
import com.sk89q.worldedit.LocalPlayer;
import com.sk89q.worldedit.entity.Player;
import com.sk89q.worldedit.util.command.Dispatcher;
import com.sk89q.worldedit.world.World;
import javax.annotation.Nullable;
@ -100,10 +98,12 @@ public interface Platform {
*/
@Nullable World matchWorld(World world);
@Deprecated
void onCommandRegistration(List<Command> commands);
void onCommandRegistration(List<Command> commands, CommandsManager<LocalPlayer> manager);
/**
* Register the commands contained within the given command dispatcher.
*
* @param dispatcher the dispatcher
*/
void registerCommands(Dispatcher dispatcher);
/**
* Register game hooks.