Merge branch 'master' into feature/mapping

Conflicts:
	src/bukkit/java/com/sk89q/worldedit/bukkit/BukkitWorld.java
	src/main/java/com/sk89q/worldedit/command/SelectionCommands.java
This commit is contained in:
sk89q 2014-07-06 21:06:10 -07:00
commit 65f451279c
22 changed files with 409 additions and 62 deletions

14
pom.xml
View File

@ -492,11 +492,23 @@
<optional>true</optional>
</dependency>
<!-- Used for running CraftBukkit from within your IDE
These are runtime-only dependencies -->
<dependency>
<groupId>org.sk89q.bukkit</groupId>
<artifactId>bukkit-classloader-check</artifactId>
<version>1.7.2-R0.3</version>
<scope>runtime</scope>
<type>jar</type>
<optional>true</optional>
</dependency>
<!-- End runtime only -->
<!-- Bukkit implementation -->
<dependency>
<groupId>org.bukkit</groupId>
<artifactId>bukkit</artifactId>
<version>1.7.2-R0.2</version>
<version>1.7.2-R0.3</version>
<scope>compile</scope>
<type>jar</type>
<optional>true</optional>

View File

@ -26,7 +26,9 @@ import com.sk89q.worldedit.LocalConfiguration;
import com.sk89q.worldedit.LocalWorld;
import com.sk89q.worldedit.ServerInterface;
import com.sk89q.worldedit.entity.Player;
import com.sk89q.worldedit.extension.platform.Actor;
import com.sk89q.worldedit.extension.platform.Capability;
import com.sk89q.worldedit.extension.platform.MultiUserPlatform;
import com.sk89q.worldedit.extension.platform.Preference;
import com.sk89q.worldedit.util.command.CommandMapping;
import com.sk89q.worldedit.util.command.Description;
@ -39,11 +41,12 @@ import org.bukkit.entity.EntityType;
import javax.annotation.Nullable;
import java.util.ArrayList;
import java.util.Collection;
import java.util.EnumMap;
import java.util.List;
import java.util.Map;
public class BukkitServerInterface extends ServerInterface {
public class BukkitServerInterface extends ServerInterface implements MultiUserPlatform {
public Server server;
public WorldEditPlugin plugin;
private CommandRegistration dynamicCommands;
@ -168,6 +171,7 @@ public class BukkitServerInterface extends ServerInterface {
public Map<Capability, Preference> getCapabilities() {
Map<Capability, Preference> capabilities = new EnumMap<Capability, Preference>(Capability.class);
capabilities.put(Capability.CONFIGURATION, Preference.NORMAL);
capabilities.put(Capability.WORLDEDIT_CUI, Preference.NORMAL);
capabilities.put(Capability.GAME_HOOKS, Preference.PREFERRED);
capabilities.put(Capability.PERMISSIONS, Preference.PREFERRED);
capabilities.put(Capability.USER_COMMANDS, Preference.PREFERRED);
@ -178,4 +182,13 @@ public class BukkitServerInterface extends ServerInterface {
public void unregisterCommands() {
dynamicCommands.unregisterCommands();
}
@Override
public Collection<Actor> getConnectedUsers() {
List<Actor> users = new ArrayList<Actor>();
for (org.bukkit.entity.Player player : Bukkit.getServer().getOnlinePlayers()) {
users.add(new BukkitPlayer(plugin, this, player));
}
return users;
}
}

View File

@ -1312,4 +1312,12 @@ public class BukkitWorld extends LocalWorld {
return null;
}
/**
* @deprecated Use {@link #setBlock(Vector, BaseBlock, boolean)}
*/
@Deprecated
public boolean setBlock(Vector pt, com.sk89q.worldedit.foundation.Block block, boolean notifyAdjacent) throws WorldEditException {
return setBlock(pt, (BaseBlock) block, notifyAdjacent);
}
}

View File

@ -23,7 +23,9 @@ import com.sk89q.worldedit.BiomeTypes;
import com.sk89q.worldedit.LocalConfiguration;
import com.sk89q.worldedit.ServerInterface;
import com.sk89q.worldedit.entity.Player;
import com.sk89q.worldedit.extension.platform.Actor;
import com.sk89q.worldedit.extension.platform.Capability;
import com.sk89q.worldedit.extension.platform.MultiUserPlatform;
import com.sk89q.worldedit.extension.platform.Preference;
import com.sk89q.worldedit.util.command.CommandMapping;
import com.sk89q.worldedit.util.command.Description;
@ -38,13 +40,19 @@ import net.minecraft.entity.EntityList;
import net.minecraft.entity.player.EntityPlayerMP;
import net.minecraft.item.Item;
import net.minecraft.server.MinecraftServer;
import net.minecraft.server.management.ServerConfigurationManager;
import net.minecraft.world.WorldServer;
import net.minecraftforge.common.DimensionManager;
import javax.annotation.Nullable;
import java.util.*;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
import java.util.EnumMap;
import java.util.List;
import java.util.Map;
class ForgePlatform extends ServerInterface {
class ForgePlatform extends ServerInterface implements MultiUserPlatform {
private final ForgeWorldEdit mod;
private final MinecraftServer server;
@ -205,6 +213,7 @@ class ForgePlatform extends ServerInterface {
public Map<Capability, Preference> getCapabilities() {
Map<Capability, Preference> capabilities = new EnumMap<Capability, Preference>(Capability.class);
capabilities.put(Capability.CONFIGURATION, Preference.PREFER_OTHERS);
capabilities.put(Capability.WORLDEDIT_CUI, Preference.NORMAL);
capabilities.put(Capability.GAME_HOOKS, Preference.NORMAL);
capabilities.put(Capability.PERMISSIONS, Preference.PREFER_OTHERS);
capabilities.put(Capability.USER_COMMANDS, Preference.NORMAL);
@ -212,4 +221,16 @@ class ForgePlatform extends ServerInterface {
return capabilities;
}
@Override
public Collection<Actor> getConnectedUsers() {
List<Actor> users = new ArrayList<Actor>();
ServerConfigurationManager scm = server.getConfigurationManager();
for (String name : scm.getAllUsernames()) {
EntityPlayerMP entity = scm.getPlayerForUsername(name);
if (entity != null) {
users.add(new ForgePlayer(entity));
}
}
return users;
}
}

View File

@ -23,8 +23,14 @@ import com.sk89q.minecraft.util.commands.Command;
import com.sk89q.minecraft.util.commands.CommandContext;
import com.sk89q.minecraft.util.commands.CommandPermissions;
import com.sk89q.minecraft.util.commands.Logging;
import com.sk89q.worldedit.*;
import com.sk89q.worldedit.EditSession;
import com.sk89q.worldedit.LocalConfiguration;
import com.sk89q.worldedit.LocalSession;
import com.sk89q.worldedit.WorldEdit;
import com.sk89q.worldedit.WorldEditException;
import com.sk89q.worldedit.WorldVector;
import com.sk89q.worldedit.entity.Player;
import com.sk89q.worldedit.util.command.parametric.Optional;
import static com.google.common.base.Preconditions.checkNotNull;
import static com.sk89q.minecraft.util.commands.Logging.LogMode.POSITION;
@ -68,13 +74,7 @@ public class NavigationCommands {
max = 1
)
@CommandPermissions("worldedit.navigation.ascend")
public void ascend(Player player, LocalSession session, EditSession editSession, CommandContext args) throws WorldEditException {
int levelsToAscend = 0;
if (args.argsLength() == 0) {
levelsToAscend = 1;
} else {
levelsToAscend = args.getInteger(0);
}
public void ascend(Player player, @Optional("1") int levelsToAscend) throws WorldEditException {
int ascentLevels = 1;
while (player.ascendLevel() && levelsToAscend != ascentLevels) {
++ascentLevels;
@ -94,13 +94,7 @@ public class NavigationCommands {
max = 1
)
@CommandPermissions("worldedit.navigation.descend")
public void descend(Player player, LocalSession session, EditSession editSession, CommandContext args) throws WorldEditException {
int levelsToDescend = 0;
if (args.argsLength() == 0) {
levelsToDescend = 1;
} else {
levelsToDescend = args.getInteger(0);
}
public void descend(Player player, @Optional("1") int levelsToDescend) throws WorldEditException {
int descentLevels = 1;
while (player.descendLevel() && levelsToDescend != descentLevels) {
++descentLevels;
@ -181,7 +175,6 @@ public class NavigationCommands {
@CommandPermissions("worldedit.navigation.up")
@Logging(POSITION)
public void up(Player player, LocalSession session, EditSession editSession, CommandContext args) throws WorldEditException {
final int distance = args.getInteger(0);
final boolean alwaysGlass = getAlwaysGlass(args);

View File

@ -449,7 +449,8 @@ public class RegionCommands {
)
@CommandPermissions("worldedit.region.forest")
@Logging(REGION)
public void forest(Player player, EditSession editSession, @Selection Region region, @Optional("tree") TreeType type, @Optional("5") double density) throws WorldEditException {
public void forest(Player player, EditSession editSession, @Selection Region region, @Optional("tree") TreeType type,
@Optional("5") @Range(min = 0, max = 100) double density) throws WorldEditException {
density = density / 100;
ForestGenerator generator = new ForestGenerator(editSession, new TreeGenerator(type));
GroundFunction ground = new GroundFunction(new ExistingBlockMask(editSession), generator);
@ -469,7 +470,7 @@ public class RegionCommands {
)
@CommandPermissions("worldedit.region.flora")
@Logging(REGION)
public void flora(Player player, EditSession editSession, @Selection Region region, @Optional("10") double density) throws WorldEditException {
public void flora(Player player, EditSession editSession, @Selection Region region, @Optional("10") @Range(min = 0, max = 100) double density) throws WorldEditException {
density = density / 100;
FloraGenerator generator = new FloraGenerator(editSession);
GroundFunction ground = new GroundFunction(new ExistingBlockMask(editSession), generator);

View File

@ -20,7 +20,6 @@
package com.sk89q.worldedit.command;
import com.sk89q.minecraft.util.commands.Command;
import com.sk89q.minecraft.util.commands.CommandAlias;
import com.sk89q.minecraft.util.commands.CommandContext;
import com.sk89q.minecraft.util.commands.CommandException;
import com.sk89q.minecraft.util.commands.CommandPermissions;
@ -706,7 +705,7 @@ public class SelectionCommands {
}
@Command(
aliases = { "/sel", ";" },
aliases = { "/sel", ";", "/desel", "/deselect" },
usage = "[cuboid|extend|poly|ellipsoid|sphere|cyl|convex]",
desc = "Choose a region selector",
min = 0,
@ -761,9 +760,4 @@ public class SelectionCommands {
session.dispatchCUISelection(player);
}
@Command(aliases = {"/desel", "/deselect"}, desc = "Deselect the current selection")
@CommandAlias("/sel")
public void deselect() {
}
}

View File

@ -22,6 +22,7 @@ package com.sk89q.worldedit.command;
import com.google.common.base.Joiner;
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.minecraft.util.commands.Logging;
import com.sk89q.worldedit.EditSession;
@ -36,6 +37,9 @@ import com.sk89q.worldedit.blocks.BaseBlock;
import com.sk89q.worldedit.entity.Player;
import com.sk89q.worldedit.extension.platform.Actor;
import com.sk89q.worldedit.extension.platform.CommandManager;
import com.sk89q.worldedit.internal.expression.Expression;
import com.sk89q.worldedit.internal.expression.ExpressionException;
import com.sk89q.worldedit.internal.expression.runtime.EvaluationException;
import com.sk89q.worldedit.patterns.Pattern;
import com.sk89q.worldedit.patterns.SingleBlockPattern;
import com.sk89q.worldedit.regions.CuboidRegion;
@ -44,6 +48,7 @@ import com.sk89q.worldedit.util.command.CommandCallable;
import com.sk89q.worldedit.util.command.CommandMapping;
import com.sk89q.worldedit.util.command.Dispatcher;
import com.sk89q.worldedit.util.command.PrimaryAliasComparator;
import com.sk89q.worldedit.util.command.binding.Text;
import com.sk89q.worldedit.util.command.parametric.Optional;
import com.sk89q.worldedit.util.formatting.ColorCodeBuilder;
import com.sk89q.worldedit.util.formatting.Style;
@ -504,6 +509,24 @@ public class UtilityCommands {
player.print("Marked " + removed + " entit(ies) for removal.");
}
@Command(
aliases = { "/calc", "/calculate", "/eval", "/evaluate", "/solve" },
usage = "<expression>",
desc = "Evaluate a mathematical expression"
)
public void calc(Actor actor, @Text String input) throws CommandException {
try {
Expression expression = Expression.compile(input);
actor.print("= " + expression.evaluate());
} catch (EvaluationException e) {
actor.printError(String.format(
"'%s' could not be parsed as a valid expression", input));
} catch (ExpressionException e) {
actor.printError(String.format(
"'%s' could not be evaluated (error: %s)", input, e.getMessage()));
}
}
@Command(
aliases = { "/help" },
usage = "[<command>]",

View File

@ -42,6 +42,26 @@ public class ParserContext {
private boolean restricted = true;
private boolean preferringWildcard;
/**
* Create a new instance.
*/
public ParserContext() {
}
/**
* Creates a copy of another instance.
*
* @param other the other instance
*/
public ParserContext(ParserContext other) {
setExtent(other.getExtent());
setSession(other.getSession());
setWorld(other.getWorld());
setActor(other.getActor());
setRestricted(other.isRestricted());
setPreferringWildcard(other.isPreferringWildcard());
}
/**
* Get the {@link Extent} set on this context.
*

View File

@ -65,6 +65,11 @@ public enum Capability {
*/
PERMISSIONS,
/**
* The capability of a platform to dispatch WorldEditCUI events.
*/
WORLDEDIT_CUI,
/**
* The capability of a platform to perform modifications to a world.
*/

View File

@ -33,6 +33,7 @@ import com.sk89q.worldedit.event.platform.CommandEvent;
import com.sk89q.worldedit.event.platform.CommandSuggestionEvent;
import com.sk89q.worldedit.internal.command.ActorAuthorizer;
import com.sk89q.worldedit.internal.command.CommandLoggingHandler;
import com.sk89q.worldedit.internal.command.UserCommandCompleter;
import com.sk89q.worldedit.internal.command.WorldEditBinding;
import com.sk89q.worldedit.internal.command.WorldEditExceptionConverter;
import com.sk89q.worldedit.session.request.Request;
@ -93,6 +94,7 @@ public final class CommandManager {
// Set up the commands manager
ParametricBuilder builder = new ParametricBuilder();
builder.setAuthorizer(new ActorAuthorizer());
builder.setDefaultCompleter(new UserCommandCompleter(platformManager));
builder.addBinding(new WorldEditBinding(worldEdit));
builder.addExceptionConverter(new WorldEditExceptionConverter(worldEdit));
builder.addInvokeListener(new LegacyCommandsHandler());

View File

@ -0,0 +1,36 @@
/*
* WorldEdit, a Minecraft world manipulation toolkit
* Copyright (C) sk89q <http://www.sk89q.com>
* Copyright (C) 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 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.worldedit.extension.platform;
import java.util.Collection;
/**
* Implements a platform with multiple connected users.
*/
public interface MultiUserPlatform extends Platform {
/**
* Get a list of connected users.
*
* @return a list of connected users
*/
Collection<Actor> getConnectedUsers();
}

View File

@ -240,7 +240,12 @@ public class PlatformManager {
permActor = player;
}
return (T) new PlayerProxy(player, permActor, getWorldForEditing(player.getWorld()));
Player cuiActor = queryCapability(Capability.WORLDEDIT_CUI).matchPlayer(player);
if (cuiActor == null) {
cuiActor = player;
}
return (T) new PlayerProxy(player, permActor, cuiActor, getWorldForEditing(player.getWorld()));
} else {
return base;
}

View File

@ -24,6 +24,7 @@ import com.sk89q.worldedit.WorldVector;
import com.sk89q.worldedit.entity.BaseEntity;
import com.sk89q.worldedit.entity.Player;
import com.sk89q.worldedit.extent.inventory.BlockBag;
import com.sk89q.worldedit.internal.cui.CUIEvent;
import com.sk89q.worldedit.util.Location;
import com.sk89q.worldedit.world.World;
@ -33,14 +34,17 @@ class PlayerProxy extends AbstractPlayerActor {
private final Player basePlayer;
private final Actor permActor;
private final Actor cuiActor;
private final World world;
PlayerProxy(Player basePlayer, Actor permActor, World world) {
PlayerProxy(Player basePlayer, Actor permActor, Actor cuiActor, World world) {
checkNotNull(basePlayer);
checkNotNull(permActor);
checkNotNull(cuiActor);
checkNotNull(world);
this.basePlayer = basePlayer;
this.permActor = permActor;
this.cuiActor = cuiActor;
this.world = world;
}
@ -128,4 +132,9 @@ class PlayerProxy extends AbstractPlayerActor {
public boolean hasPermission(String perm) {
return permActor.hasPermission(perm);
}
@Override
public void dispatchCUIEvent(CUIEvent event) {
cuiActor.dispatchCUIEvent(event);
}
}

View File

@ -132,7 +132,10 @@ class DefaultMaskParser extends InputParser<Mask> {
}
default:
return new BlockMask(extent, worldEdit.getBlockRegistry().parseFromListInput(component, context));
ParserContext tempContext = new ParserContext(context);
tempContext.setRestricted(false);
tempContext.setPreferringWildcard(true);
return new BlockMask(extent, worldEdit.getBlockRegistry().parseFromListInput(component, tempContext));
}
}

View File

@ -0,0 +1,72 @@
/*
* WorldEdit, a Minecraft world manipulation toolkit
* Copyright (C) sk89q <http://www.sk89q.com>
* Copyright (C) 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 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.worldedit.internal.command;
import com.sk89q.minecraft.util.commands.CommandException;
import com.sk89q.minecraft.util.commands.CommandLocals;
import com.sk89q.worldedit.extension.platform.Actor;
import com.sk89q.worldedit.extension.platform.Capability;
import com.sk89q.worldedit.extension.platform.MultiUserPlatform;
import com.sk89q.worldedit.extension.platform.Platform;
import com.sk89q.worldedit.extension.platform.PlatformManager;
import com.sk89q.worldedit.util.command.CommandCompleter;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import java.util.List;
import static com.google.common.base.Preconditions.checkNotNull;
/**
* Provides the names of connected users as suggestions.
*/
public class UserCommandCompleter implements CommandCompleter {
private final PlatformManager platformManager;
/**
* Create a new instance.
*
* @param platformManager the platform manager
*/
public UserCommandCompleter(PlatformManager platformManager) {
checkNotNull(platformManager);
this.platformManager = platformManager;
}
@Override
public List<String> getSuggestions(String arguments, CommandLocals locals) throws CommandException {
Platform platform = platformManager.queryCapability(Capability.USER_COMMANDS);
if (platform instanceof MultiUserPlatform) {
List<String> suggestions = new ArrayList<String>();
Collection<Actor> users = ((MultiUserPlatform) platform).getConnectedUsers();
for (Actor user : users) {
if (user.getName().toLowerCase().startsWith(arguments.toLowerCase().trim())) {
suggestions.add(user.getName());
}
}
return suggestions;
} else {
return Collections.emptyList();
}
}
}

View File

@ -22,12 +22,10 @@ package com.sk89q.worldedit.util.command;
import com.sk89q.minecraft.util.commands.CommandException;
import com.sk89q.minecraft.util.commands.CommandLocals;
import java.util.List;
/**
* A command that can be executed.
*/
public interface CommandCallable {
public interface CommandCallable extends CommandCompleter {
/**
* Execute the correct command based on the input.
@ -42,16 +40,6 @@ public interface CommandCallable {
*/
boolean call(String arguments, CommandLocals locals, String[] parentCommands) throws CommandException;
/**
* Get a list of suggestions based on input.
*
* @param arguments the arguments entered up to this point
* @param locals the locals
* @return a list of suggestions
* @throws CommandException thrown if there was a parsing error
*/
List<String> getSuggestions(String arguments, CommandLocals locals) throws CommandException;
/**
* Get an object describing this command.
*

View File

@ -0,0 +1,42 @@
/*
* WorldEdit, a Minecraft world manipulation toolkit
* Copyright (C) sk89q <http://www.sk89q.com>
* Copyright (C) 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 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.worldedit.util.command;
import com.sk89q.minecraft.util.commands.CommandException;
import com.sk89q.minecraft.util.commands.CommandLocals;
import java.util.List;
/**
* Provides a method that can provide tab completion for commands.
*/
public interface CommandCompleter {
/**
* Get a list of suggestions based on input.
*
* @param arguments the arguments entered up to this point
* @param locals the locals
* @return a list of suggestions
* @throws CommandException thrown if there was a parsing error
*/
List<String> getSuggestions(String arguments, CommandLocals locals) throws CommandException;
}

View File

@ -0,0 +1,38 @@
/*
* WorldEdit, a Minecraft world manipulation toolkit
* Copyright (C) sk89q <http://www.sk89q.com>
* Copyright (C) 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 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.worldedit.util.command;
import com.sk89q.minecraft.util.commands.CommandException;
import com.sk89q.minecraft.util.commands.CommandLocals;
import java.util.Collections;
import java.util.List;
/**
* Always returns an empty list of suggestions.
*/
public class NullCompleter implements CommandCompleter {
@Override
public List<String> getSuggestions(String arguments, CommandLocals locals) throws CommandException {
return Collections.emptyList();
}
}

View File

@ -19,8 +19,16 @@
package com.sk89q.worldedit.util.command.binding;
import com.sk89q.worldedit.util.command.parametric.*;
import com.sk89q.worldedit.internal.expression.Expression;
import com.sk89q.worldedit.internal.expression.ExpressionException;
import com.sk89q.worldedit.internal.expression.runtime.EvaluationException;
import com.sk89q.worldedit.util.command.parametric.ArgumentStack;
import com.sk89q.worldedit.util.command.parametric.BindingBehavior;
import com.sk89q.worldedit.util.command.parametric.BindingHelper;
import com.sk89q.worldedit.util.command.parametric.BindingMatch;
import com.sk89q.worldedit.util.command.parametric.ParameterException;
import javax.annotation.Nullable;
import java.lang.annotation.Annotation;
/**
@ -84,6 +92,35 @@ public final class PrimitiveBindings extends BindingHelper {
return context.nextBoolean();
}
/**
* Try to parse numeric input as either a number or a mathematical expression.
*
* @param input input
* @return a number
* @throws ParameterException thrown on parse error
*/
private @Nullable Double parseNumericInput(@Nullable String input) throws ParameterException {
if (input == null) {
return null;
}
try {
return Double.parseDouble(input);
} catch (NumberFormatException e1) {
try {
Expression expression = Expression.compile(input);
return expression.evaluate();
} catch (EvaluationException e) {
throw new ParameterException(String.format(
"Expected '%s' to be a valid number (or a valid mathematical expression)", input));
} catch (ExpressionException e) {
throw new ParameterException(String.format(
"Expected '%s' to be a number or valid math expression (error: %s)", input, e.getMessage()));
}
}
}
/**
* Gets a type from a {@link ArgumentStack}.
*
@ -96,13 +133,15 @@ public final class PrimitiveBindings extends BindingHelper {
behavior = BindingBehavior.CONSUMES,
consumedCount = 1,
provideModifiers = true)
public Integer getInteger(ArgumentStack context, Annotation[] modifiers)
throws ParameterException {
Integer v = context.nextInt();
public Integer getInteger(ArgumentStack context, Annotation[] modifiers) throws ParameterException {
Double v = parseNumericInput(context.next());
if (v != null) {
validate(v, modifiers);
int intValue = v.intValue();
validate(intValue, modifiers);
return intValue;
} else {
return null;
}
return v;
}
/**
@ -117,8 +156,7 @@ public final class PrimitiveBindings extends BindingHelper {
behavior = BindingBehavior.CONSUMES,
consumedCount = 1,
provideModifiers = true)
public Short getShort(ArgumentStack context, Annotation[] modifiers)
throws ParameterException {
public Short getShort(ArgumentStack context, Annotation[] modifiers) throws ParameterException {
Integer v = getInteger(context, modifiers);
if (v != null) {
return v.shortValue();
@ -138,13 +176,14 @@ public final class PrimitiveBindings extends BindingHelper {
behavior = BindingBehavior.CONSUMES,
consumedCount = 1,
provideModifiers = true)
public Double getDouble(ArgumentStack context, Annotation[] modifiers)
throws ParameterException {
Double v = context.nextDouble();
public Double getDouble(ArgumentStack context, Annotation[] modifiers) throws ParameterException {
Double v = parseNumericInput(context.next());
if (v != null) {
validate(v, modifiers);
}
return v;
} else {
return null;
}
}
/**
@ -159,8 +198,7 @@ public final class PrimitiveBindings extends BindingHelper {
behavior = BindingBehavior.CONSUMES,
consumedCount = 1,
provideModifiers = true)
public Float getFloat(ArgumentStack context, Annotation[] modifiers)
throws ParameterException {
public Float getFloat(ArgumentStack context, Annotation[] modifiers) throws ParameterException {
Double v = getDouble(context, modifiers);
if (v != null) {
return v.floatValue();

View File

@ -27,7 +27,9 @@ import com.sk89q.minecraft.util.commands.CommandPermissions;
import com.sk89q.worldedit.util.auth.Authorizer;
import com.sk89q.worldedit.util.auth.NullAuthorizer;
import com.sk89q.worldedit.util.command.CommandCallable;
import com.sk89q.worldedit.util.command.CommandCompleter;
import com.sk89q.worldedit.util.command.Dispatcher;
import com.sk89q.worldedit.util.command.NullCompleter;
import com.sk89q.worldedit.util.command.binding.PrimitiveBindings;
import com.sk89q.worldedit.util.command.binding.StandardBindings;
import com.sk89q.worldedit.util.command.binding.Switch;
@ -57,6 +59,7 @@ public class ParametricBuilder {
private final List<InvokeListener> invokeListeners = new ArrayList<InvokeListener>();
private final List<ExceptionConverter> exceptionConverters = new ArrayList<ExceptionConverter>();
private Authorizer authorizer = new NullAuthorizer();
private CommandCompleter defaultCompleter = new NullCompleter();
/**
* Create a new builder.
@ -225,4 +228,26 @@ public class ParametricBuilder {
checkNotNull(authorizer);
this.authorizer = authorizer;
}
/**
* Get the default command suggestions provider that will be used if
* no suggestions are available.
*
* @return the default command completer
*/
public CommandCompleter getDefaultCompleter() {
return defaultCompleter;
}
/**
* Set the default command suggestions provider that will be used if
* no suggestions are available.
*
* @param defaultCompleter the default command completer
*/
public void setDefaultCompleter(CommandCompleter defaultCompleter) {
checkNotNull(defaultCompleter);
this.defaultCompleter = defaultCompleter;
}
}

View File

@ -41,7 +41,6 @@ import java.lang.reflect.Method;
import java.lang.reflect.Type;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.HashSet;
import java.util.List;
import java.util.Set;
@ -273,8 +272,8 @@ class ParametricCallable implements CommandCallable {
}
@Override
public List<String> getSuggestions(String stringArguments, CommandLocals locals) throws CommandException {
return Collections.emptyList();
public List<String> getSuggestions(String arguments, CommandLocals locals) throws CommandException {
return builder.getDefaultCompleter().getSuggestions(arguments, locals);
}
/**