Always try every route to find a matching command

This commit is contained in:
Nathan Adams 2014-09-29 11:56:24 +02:00
parent 4b6abf4084
commit 6a8d067cf9
3 changed files with 60 additions and 21 deletions

View file

@ -3,6 +3,7 @@ package net.minecraft.commands;
import net.minecraft.commands.builder.LiteralArgumentBuilder;
import net.minecraft.commands.context.CommandContext;
import net.minecraft.commands.context.CommandContextBuilder;
import net.minecraft.commands.exceptions.ArgumentValidationException;
import net.minecraft.commands.exceptions.CommandException;
import net.minecraft.commands.exceptions.IllegalArgumentSyntaxException;
import net.minecraft.commands.exceptions.UnknownCommandException;
@ -19,35 +20,33 @@ public class CommandDispatcher {
}
public void execute(String command) throws CommandException {
CommandContextBuilder contextBuilder = new CommandContextBuilder();
CommandNode node = root;
CommandContext context = parseNodes(root, command, new CommandContextBuilder());
context.getCommand().run(context);
}
while (command.length() > 0 && !node.getChildren().isEmpty()) {
protected CommandContext parseNodes(CommandNode node, String command, CommandContextBuilder contextBuilder) throws IllegalArgumentSyntaxException, ArgumentValidationException, UnknownCommandException {
IllegalArgumentSyntaxException exception = null;
for (CommandNode child : node.getChildren()) {
try {
command = child.parse(command, contextBuilder);
CommandContextBuilder context = contextBuilder.copy();
String remaining = child.parse(command, context);
if (child.getCommand() != null) {
contextBuilder.withCommand(child.getCommand());
context.withCommand(child.getCommand());
}
node = child;
break;
return parseNodes(child, remaining, context);
} catch (IllegalArgumentSyntaxException ex) {
exception = ex;
}
}
if (exception != null) {
break;
throw exception;
}
}
if (command.length() > 0) {
throw new UnknownCommandException();
}
CommandContext context = contextBuilder.build();
context.getCommand().run(context);
return contextBuilder.build();
}
}

View file

@ -26,6 +26,13 @@ public class CommandContextBuilder {
return this;
}
public CommandContextBuilder copy() {
CommandContextBuilder copy = new CommandContextBuilder();
copy.command = this.command;
copy.arguments.putAll(this.arguments);
return copy;
}
public CommandContext build() {
return new CommandContext(arguments, command);
}

View file

@ -1,6 +1,7 @@
package net.minecraft.commands;
import net.minecraft.commands.context.CommandContext;
import net.minecraft.commands.exceptions.IllegalArgumentSyntaxException;
import net.minecraft.commands.exceptions.UnknownCommandException;
import org.junit.Before;
import org.junit.Test;
@ -44,6 +45,38 @@ public class CommandDispatcherTest {
verify(command, times(2)).run(any(CommandContext.class));
}
@Test
public void testCreateAndExecuteOverlappingCommands() throws Exception {
Command one = mock(Command.class);
Command two = mock(Command.class);
Command three = mock(Command.class);
subject.register(
literal("foo").then(
argument("one", integer()).then(
literal("one").executes(one)
)
).then(
argument("two", integer()).then(
literal("two").executes(two)
)
).then(
argument("three", integer()).then(
literal("three").executes(three)
)
)
);
subject.execute("foo 1 one");
verify(one).run(any(CommandContext.class));
subject.execute("foo 2 two");
verify(two).run(any(CommandContext.class));
subject.execute("foo 3 three");
verify(three).run(any(CommandContext.class));
}
@Test(expected = UnknownCommandException.class)
public void testExecuteUnknownCommand() throws Exception {
subject.execute("foo");
@ -71,7 +104,7 @@ public class CommandDispatcherTest {
verify(subCommand).run(any(CommandContext.class));
}
@Test(expected = UnknownCommandException.class)
@Test(expected = IllegalArgumentSyntaxException.class)
public void testExecuteInvalidSubcommand() throws Exception {
subject.register(literal("foo").then(
argument("bar", integer())