From 1f6e31dae84d3bb8d216bec7b4023c444258ae21 Mon Sep 17 00:00:00 2001 From: sk89q Date: Thu, 3 Jul 2014 03:33:16 -0700 Subject: [PATCH 01/11] Changed /ascend and /descend to get arguments via injection. --- .../worldedit/command/NavigationCommands.java | 25 +++++++------------ 1 file changed, 9 insertions(+), 16 deletions(-) diff --git a/src/main/java/com/sk89q/worldedit/command/NavigationCommands.java b/src/main/java/com/sk89q/worldedit/command/NavigationCommands.java index ecfeef15d..4cb581e3d 100644 --- a/src/main/java/com/sk89q/worldedit/command/NavigationCommands.java +++ b/src/main/java/com/sk89q/worldedit/command/NavigationCommands.java @@ -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); From 6c4a321d6101a42886f072e44df21ee74193b0e6 Mon Sep 17 00:00:00 2001 From: sk89q Date: Thu, 3 Jul 2014 03:33:57 -0700 Subject: [PATCH 02/11] Added support for mathematical expressions for numeric arguments in commands. This only works for commands that have been ported over to the new command framework. --- .../command/binding/PrimitiveBindings.java | 66 +++++++++++++++---- 1 file changed, 52 insertions(+), 14 deletions(-) diff --git a/src/main/java/com/sk89q/worldedit/util/command/binding/PrimitiveBindings.java b/src/main/java/com/sk89q/worldedit/util/command/binding/PrimitiveBindings.java index a4ed7ab0c..2a5ee0ccf 100644 --- a/src/main/java/com/sk89q/worldedit/util/command/binding/PrimitiveBindings.java +++ b/src/main/java/com/sk89q/worldedit/util/command/binding/PrimitiveBindings.java @@ -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; } - return v; } /** @@ -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(); From 51a540dab1251ab8ab2b4c8787f5b2015578ab2f Mon Sep 17 00:00:00 2001 From: sk89q Date: Thu, 3 Jul 2014 03:34:19 -0700 Subject: [PATCH 03/11] Added //calc, //eval, etc. to evaluate mathematical expressions. --- .../worldedit/command/UtilityCommands.java | 23 +++++++++++++++++++ 1 file changed, 23 insertions(+) diff --git a/src/main/java/com/sk89q/worldedit/command/UtilityCommands.java b/src/main/java/com/sk89q/worldedit/command/UtilityCommands.java index d57bedd28..d1e0852d8 100644 --- a/src/main/java/com/sk89q/worldedit/command/UtilityCommands.java +++ b/src/main/java/com/sk89q/worldedit/command/UtilityCommands.java @@ -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 = "", + 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 = "[]", From 63605a84171b989d89700f479d7ddccf4b919dd3 Mon Sep 17 00:00:00 2001 From: sk89q Date: Sat, 5 Jul 2014 16:40:07 -0700 Subject: [PATCH 04/11] [Bukkit] Added shim method for setBlock(..., foundation.Block, ...). --- .../java/com/sk89q/worldedit/bukkit/BukkitWorld.java | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/src/bukkit/java/com/sk89q/worldedit/bukkit/BukkitWorld.java b/src/bukkit/java/com/sk89q/worldedit/bukkit/BukkitWorld.java index 3f32fefda..4c73526d3 100644 --- a/src/bukkit/java/com/sk89q/worldedit/bukkit/BukkitWorld.java +++ b/src/bukkit/java/com/sk89q/worldedit/bukkit/BukkitWorld.java @@ -1259,4 +1259,13 @@ public class BukkitWorld extends LocalWorld { return super.setBlock(pt, block, notifyAdjacent); } + + /** + * @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); + } + } From bc92e43be0b30eece2d9e85638f7953832784093 Mon Sep 17 00:00:00 2001 From: Wyatt Childers Date: Sun, 6 Jul 2014 20:13:27 -0400 Subject: [PATCH 05/11] Adds Platform support for WorldEdit CUI --- .../sk89q/worldedit/bukkit/BukkitServerInterface.java | 1 + .../java/com/sk89q/worldedit/forge/ForgePlatform.java | 1 + .../worldedit/extension/platform/Capability.java | 5 +++++ .../worldedit/extension/platform/PlatformManager.java | 7 ++++++- .../worldedit/extension/platform/PlayerProxy.java | 11 ++++++++++- 5 files changed, 23 insertions(+), 2 deletions(-) diff --git a/src/bukkit/java/com/sk89q/worldedit/bukkit/BukkitServerInterface.java b/src/bukkit/java/com/sk89q/worldedit/bukkit/BukkitServerInterface.java index bf08bf45a..f67d2372d 100644 --- a/src/bukkit/java/com/sk89q/worldedit/bukkit/BukkitServerInterface.java +++ b/src/bukkit/java/com/sk89q/worldedit/bukkit/BukkitServerInterface.java @@ -168,6 +168,7 @@ public class BukkitServerInterface extends ServerInterface { public Map getCapabilities() { Map capabilities = new EnumMap(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); diff --git a/src/forge/java/com/sk89q/worldedit/forge/ForgePlatform.java b/src/forge/java/com/sk89q/worldedit/forge/ForgePlatform.java index 818a14573..9451908ad 100644 --- a/src/forge/java/com/sk89q/worldedit/forge/ForgePlatform.java +++ b/src/forge/java/com/sk89q/worldedit/forge/ForgePlatform.java @@ -205,6 +205,7 @@ class ForgePlatform extends ServerInterface { public Map getCapabilities() { Map capabilities = new EnumMap(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); diff --git a/src/main/java/com/sk89q/worldedit/extension/platform/Capability.java b/src/main/java/com/sk89q/worldedit/extension/platform/Capability.java index 61ee2bfb8..a753b0fd2 100644 --- a/src/main/java/com/sk89q/worldedit/extension/platform/Capability.java +++ b/src/main/java/com/sk89q/worldedit/extension/platform/Capability.java @@ -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. */ diff --git a/src/main/java/com/sk89q/worldedit/extension/platform/PlatformManager.java b/src/main/java/com/sk89q/worldedit/extension/platform/PlatformManager.java index 3e70e2483..a62bc247a 100644 --- a/src/main/java/com/sk89q/worldedit/extension/platform/PlatformManager.java +++ b/src/main/java/com/sk89q/worldedit/extension/platform/PlatformManager.java @@ -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; } diff --git a/src/main/java/com/sk89q/worldedit/extension/platform/PlayerProxy.java b/src/main/java/com/sk89q/worldedit/extension/platform/PlayerProxy.java index ce14651be..b2569490f 100644 --- a/src/main/java/com/sk89q/worldedit/extension/platform/PlayerProxy.java +++ b/src/main/java/com/sk89q/worldedit/extension/platform/PlayerProxy.java @@ -23,6 +23,7 @@ import com.sk89q.worldedit.Vector; import com.sk89q.worldedit.WorldVector; 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; @@ -32,14 +33,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; } @@ -122,4 +126,9 @@ class PlayerProxy extends AbstractPlayerActor { public boolean hasPermission(String perm) { return permActor.hasPermission(perm); } + + @Override + public void dispatchCUIEvent(CUIEvent event) { + cuiActor.dispatchCUIEvent(event); + } } From f1649dbf51a4e6cc5d423761aa898a58aa257eb8 Mon Sep 17 00:00:00 2001 From: sk89q Date: Sun, 6 Jul 2014 16:38:46 -0700 Subject: [PATCH 06/11] [Bukkit] Added runtime dependency for running Bukkit. --- pom.xml | 14 +++++++++++++- 1 file changed, 13 insertions(+), 1 deletion(-) diff --git a/pom.xml b/pom.xml index 89e1d0efc..24b512526 100644 --- a/pom.xml +++ b/pom.xml @@ -492,11 +492,23 @@ true + + + org.sk89q.bukkit + bukkit-classloader-check + 1.7.2-R0.3 + runtime + jar + true + + + org.bukkit bukkit - 1.7.2-R0.2 + 1.7.2-R0.3 compile jar true From 6f0fde47b02bffd2c2bea0bbd17f1bb6feca3ae6 Mon Sep 17 00:00:00 2001 From: sk89q Date: Sun, 6 Jul 2014 17:22:49 -0700 Subject: [PATCH 07/11] Restored tab completion of player names. Fixes WORLDEDIT-3144. --- .../bukkit/BukkitServerInterface.java | 14 +++- .../sk89q/worldedit/forge/ForgePlatform.java | 24 ++++++- .../extension/platform/CommandManager.java | 2 + .../extension/platform/MultiUserPlatform.java | 36 ++++++++++ .../command/UserCommandCompleter.java | 72 +++++++++++++++++++ .../util/command/CommandCallable.java | 14 +--- .../util/command/CommandCompleter.java | 42 +++++++++++ .../worldedit/util/command/NullCompleter.java | 38 ++++++++++ .../command/parametric/ParametricBuilder.java | 25 +++++++ .../parametric/ParametricCallable.java | 5 +- 10 files changed, 253 insertions(+), 19 deletions(-) create mode 100644 src/main/java/com/sk89q/worldedit/extension/platform/MultiUserPlatform.java create mode 100644 src/main/java/com/sk89q/worldedit/internal/command/UserCommandCompleter.java create mode 100644 src/main/java/com/sk89q/worldedit/util/command/CommandCompleter.java create mode 100644 src/main/java/com/sk89q/worldedit/util/command/NullCompleter.java diff --git a/src/bukkit/java/com/sk89q/worldedit/bukkit/BukkitServerInterface.java b/src/bukkit/java/com/sk89q/worldedit/bukkit/BukkitServerInterface.java index f67d2372d..1bf4c6a61 100644 --- a/src/bukkit/java/com/sk89q/worldedit/bukkit/BukkitServerInterface.java +++ b/src/bukkit/java/com/sk89q/worldedit/bukkit/BukkitServerInterface.java @@ -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; @@ -179,4 +182,13 @@ public class BukkitServerInterface extends ServerInterface { public void unregisterCommands() { dynamicCommands.unregisterCommands(); } + + @Override + public Collection getConnectedUsers() { + List users = new ArrayList(); + for (org.bukkit.entity.Player player : Bukkit.getServer().getOnlinePlayers()) { + users.add(new BukkitPlayer(plugin, this, player)); + } + return users; + } } diff --git a/src/forge/java/com/sk89q/worldedit/forge/ForgePlatform.java b/src/forge/java/com/sk89q/worldedit/forge/ForgePlatform.java index 9451908ad..62c04afb3 100644 --- a/src/forge/java/com/sk89q/worldedit/forge/ForgePlatform.java +++ b/src/forge/java/com/sk89q/worldedit/forge/ForgePlatform.java @@ -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; @@ -213,4 +221,16 @@ class ForgePlatform extends ServerInterface { return capabilities; } + @Override + public Collection getConnectedUsers() { + List users = new ArrayList(); + ServerConfigurationManager scm = server.getConfigurationManager(); + for (String name : scm.getAllUsernames()) { + EntityPlayerMP entity = scm.getPlayerForUsername(name); + if (entity != null) { + users.add(new ForgePlayer(entity)); + } + } + return users; + } } diff --git a/src/main/java/com/sk89q/worldedit/extension/platform/CommandManager.java b/src/main/java/com/sk89q/worldedit/extension/platform/CommandManager.java index 9c71cfe69..466903332 100644 --- a/src/main/java/com/sk89q/worldedit/extension/platform/CommandManager.java +++ b/src/main/java/com/sk89q/worldedit/extension/platform/CommandManager.java @@ -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()); diff --git a/src/main/java/com/sk89q/worldedit/extension/platform/MultiUserPlatform.java b/src/main/java/com/sk89q/worldedit/extension/platform/MultiUserPlatform.java new file mode 100644 index 000000000..6fa94e017 --- /dev/null +++ b/src/main/java/com/sk89q/worldedit/extension/platform/MultiUserPlatform.java @@ -0,0 +1,36 @@ +/* + * WorldEdit, a Minecraft world manipulation toolkit + * Copyright (C) sk89q + * 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 . + */ + +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 getConnectedUsers(); + +} diff --git a/src/main/java/com/sk89q/worldedit/internal/command/UserCommandCompleter.java b/src/main/java/com/sk89q/worldedit/internal/command/UserCommandCompleter.java new file mode 100644 index 000000000..63957cbca --- /dev/null +++ b/src/main/java/com/sk89q/worldedit/internal/command/UserCommandCompleter.java @@ -0,0 +1,72 @@ +/* + * WorldEdit, a Minecraft world manipulation toolkit + * Copyright (C) sk89q + * 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 . + */ + +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 getSuggestions(String arguments, CommandLocals locals) throws CommandException { + Platform platform = platformManager.queryCapability(Capability.USER_COMMANDS); + if (platform instanceof MultiUserPlatform) { + List suggestions = new ArrayList(); + Collection 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(); + } + } + +} diff --git a/src/main/java/com/sk89q/worldedit/util/command/CommandCallable.java b/src/main/java/com/sk89q/worldedit/util/command/CommandCallable.java index 3c75884c5..85b4133a0 100644 --- a/src/main/java/com/sk89q/worldedit/util/command/CommandCallable.java +++ b/src/main/java/com/sk89q/worldedit/util/command/CommandCallable.java @@ -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. @@ -41,16 +39,6 @@ public interface CommandCallable { * @throws CommandException thrown on a command error */ 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 getSuggestions(String arguments, CommandLocals locals) throws CommandException; /** * Get an object describing this command. diff --git a/src/main/java/com/sk89q/worldedit/util/command/CommandCompleter.java b/src/main/java/com/sk89q/worldedit/util/command/CommandCompleter.java new file mode 100644 index 000000000..19bf47d60 --- /dev/null +++ b/src/main/java/com/sk89q/worldedit/util/command/CommandCompleter.java @@ -0,0 +1,42 @@ +/* + * WorldEdit, a Minecraft world manipulation toolkit + * Copyright (C) sk89q + * 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 . + */ + +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 getSuggestions(String arguments, CommandLocals locals) throws CommandException; + +} diff --git a/src/main/java/com/sk89q/worldedit/util/command/NullCompleter.java b/src/main/java/com/sk89q/worldedit/util/command/NullCompleter.java new file mode 100644 index 000000000..10850c696 --- /dev/null +++ b/src/main/java/com/sk89q/worldedit/util/command/NullCompleter.java @@ -0,0 +1,38 @@ +/* + * WorldEdit, a Minecraft world manipulation toolkit + * Copyright (C) sk89q + * 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 . + */ + +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 getSuggestions(String arguments, CommandLocals locals) throws CommandException { + return Collections.emptyList(); + } + +} diff --git a/src/main/java/com/sk89q/worldedit/util/command/parametric/ParametricBuilder.java b/src/main/java/com/sk89q/worldedit/util/command/parametric/ParametricBuilder.java index dd96c4a2a..c7b94ebde 100644 --- a/src/main/java/com/sk89q/worldedit/util/command/parametric/ParametricBuilder.java +++ b/src/main/java/com/sk89q/worldedit/util/command/parametric/ParametricBuilder.java @@ -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 invokeListeners = new ArrayList(); private final List exceptionConverters = new ArrayList(); 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; + } + } diff --git a/src/main/java/com/sk89q/worldedit/util/command/parametric/ParametricCallable.java b/src/main/java/com/sk89q/worldedit/util/command/parametric/ParametricCallable.java index a96434ac0..5a7836264 100644 --- a/src/main/java/com/sk89q/worldedit/util/command/parametric/ParametricCallable.java +++ b/src/main/java/com/sk89q/worldedit/util/command/parametric/ParametricCallable.java @@ -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 getSuggestions(String stringArguments, CommandLocals locals) throws CommandException { - return Collections.emptyList(); + public List getSuggestions(String arguments, CommandLocals locals) throws CommandException { + return builder.getDefaultCompleter().getSuggestions(arguments, locals); } /** From e9ca6189618515d6e020f51516ec424af290d5cd Mon Sep 17 00:00:00 2001 From: sk89q Date: Sun, 6 Jul 2014 17:29:17 -0700 Subject: [PATCH 08/11] Fixes //desel no longer working. Closes WORLDEDIT-3146. --- .../worldedit/command/SelectionCommands.java | 37 ++++++++----------- 1 file changed, 15 insertions(+), 22 deletions(-) diff --git a/src/main/java/com/sk89q/worldedit/command/SelectionCommands.java b/src/main/java/com/sk89q/worldedit/command/SelectionCommands.java index 20cfba116..ba5144f9e 100644 --- a/src/main/java/com/sk89q/worldedit/command/SelectionCommands.java +++ b/src/main/java/com/sk89q/worldedit/command/SelectionCommands.java @@ -19,23 +19,12 @@ package com.sk89q.worldedit.command; -import static com.sk89q.minecraft.util.commands.Logging.LogMode.POSITION; -import static com.sk89q.minecraft.util.commands.Logging.LogMode.REGION; - -import java.util.ArrayList; -import java.util.List; -import java.util.Set; - 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.CommandPermissions; import com.sk89q.minecraft.util.commands.Logging; -import com.sk89q.worldedit.entity.Player; -import com.sk89q.worldedit.util.Countable; import com.sk89q.worldedit.CuboidClipboard; import com.sk89q.worldedit.EditSession; -import com.sk89q.worldedit.LocalPlayer; import com.sk89q.worldedit.LocalSession; import com.sk89q.worldedit.Vector; import com.sk89q.worldedit.Vector2D; @@ -43,18 +32,27 @@ import com.sk89q.worldedit.WorldEdit; import com.sk89q.worldedit.WorldEditException; import com.sk89q.worldedit.blocks.BaseBlock; import com.sk89q.worldedit.blocks.BlockType; -import com.sk89q.worldedit.world.World; -import com.sk89q.worldedit.world.storage.ChunkStore; +import com.sk89q.worldedit.entity.Player; +import com.sk89q.worldedit.regions.Region; +import com.sk89q.worldedit.regions.RegionOperationException; +import com.sk89q.worldedit.regions.RegionSelector; import com.sk89q.worldedit.regions.selector.ConvexPolyhedralRegionSelector; import com.sk89q.worldedit.regions.selector.CuboidRegionSelector; import com.sk89q.worldedit.regions.selector.CylinderRegionSelector; import com.sk89q.worldedit.regions.selector.EllipsoidRegionSelector; import com.sk89q.worldedit.regions.selector.ExtendingCuboidRegionSelector; import com.sk89q.worldedit.regions.selector.Polygonal2DRegionSelector; -import com.sk89q.worldedit.regions.Region; -import com.sk89q.worldedit.regions.RegionOperationException; -import com.sk89q.worldedit.regions.RegionSelector; import com.sk89q.worldedit.regions.selector.SphereRegionSelector; +import com.sk89q.worldedit.util.Countable; +import com.sk89q.worldedit.world.World; +import com.sk89q.worldedit.world.storage.ChunkStore; + +import java.util.ArrayList; +import java.util.List; +import java.util.Set; + +import static com.sk89q.minecraft.util.commands.Logging.LogMode.POSITION; +import static com.sk89q.minecraft.util.commands.Logging.LogMode.REGION; /** * Selection commands. @@ -710,7 +708,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, @@ -765,9 +763,4 @@ public class SelectionCommands { session.dispatchCUISelection(player); } - @Command(aliases = {"/desel", "/deselect"}, desc = "Deselect the current selection") - @CommandAlias("/sel") - public void deselect() { - - } } From 85f014e256bcbd359a289b9b8116e283982a9a2d Mon Sep 17 00:00:00 2001 From: sk89q Date: Sun, 6 Jul 2014 17:34:08 -0700 Subject: [PATCH 09/11] Clamp acceptable density for //flora and //forest. Fixes WORLDEDIT-3148. --- .../java/com/sk89q/worldedit/command/RegionCommands.java | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/src/main/java/com/sk89q/worldedit/command/RegionCommands.java b/src/main/java/com/sk89q/worldedit/command/RegionCommands.java index e8dd44277..5f82d1b55 100644 --- a/src/main/java/com/sk89q/worldedit/command/RegionCommands.java +++ b/src/main/java/com/sk89q/worldedit/command/RegionCommands.java @@ -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); From 68e5d5926a4aefbde893b771069158a9edd3ab07 Mon Sep 17 00:00:00 2001 From: sk89q Date: Sun, 6 Jul 2014 18:10:30 -0700 Subject: [PATCH 10/11] Allow masks parsed from input to ignore the blacklist. Fixes WORLDEDIT-3149. --- .../extension/input/ParserContext.java | 20 +++++++++++++++++++ .../extension/registry/DefaultMaskParser.java | 4 +++- 2 files changed, 23 insertions(+), 1 deletion(-) diff --git a/src/main/java/com/sk89q/worldedit/extension/input/ParserContext.java b/src/main/java/com/sk89q/worldedit/extension/input/ParserContext.java index 49b345d71..9d2b56f19 100644 --- a/src/main/java/com/sk89q/worldedit/extension/input/ParserContext.java +++ b/src/main/java/com/sk89q/worldedit/extension/input/ParserContext.java @@ -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. * diff --git a/src/main/java/com/sk89q/worldedit/extension/registry/DefaultMaskParser.java b/src/main/java/com/sk89q/worldedit/extension/registry/DefaultMaskParser.java index b85b9ff1f..d8521fb9c 100644 --- a/src/main/java/com/sk89q/worldedit/extension/registry/DefaultMaskParser.java +++ b/src/main/java/com/sk89q/worldedit/extension/registry/DefaultMaskParser.java @@ -132,7 +132,9 @@ class DefaultMaskParser extends InputParser { } default: - return new BlockMask(extent, worldEdit.getBlockRegistry().parseFromListInput(component, context)); + ParserContext tempContext = new ParserContext(context); + tempContext.setRestricted(false); + return new BlockMask(extent, worldEdit.getBlockRegistry().parseFromListInput(component, tempContext)); } } From d74237b15e0c00ab634bce36a1d5fa41f08d417c Mon Sep 17 00:00:00 2001 From: sk89q Date: Sun, 6 Jul 2014 18:12:15 -0700 Subject: [PATCH 11/11] Fixes masks parsed from input not using block wildcards. Closes WORLDEDIT-3147. --- .../sk89q/worldedit/extension/registry/DefaultMaskParser.java | 1 + 1 file changed, 1 insertion(+) diff --git a/src/main/java/com/sk89q/worldedit/extension/registry/DefaultMaskParser.java b/src/main/java/com/sk89q/worldedit/extension/registry/DefaultMaskParser.java index d8521fb9c..304a49b60 100644 --- a/src/main/java/com/sk89q/worldedit/extension/registry/DefaultMaskParser.java +++ b/src/main/java/com/sk89q/worldedit/extension/registry/DefaultMaskParser.java @@ -134,6 +134,7 @@ class DefaultMaskParser extends InputParser { default: ParserContext tempContext = new ParserContext(context); tempContext.setRestricted(false); + tempContext.setPreferringWildcard(true); return new BlockMask(extent, worldEdit.getBlockRegistry().parseFromListInput(component, tempContext)); } }