Always try every route to find a matching command
This commit is contained in:
parent
4b6abf4084
commit
6a8d067cf9
3 changed files with 60 additions and 21 deletions
|
@ -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()) {
|
||||
IllegalArgumentSyntaxException exception = null;
|
||||
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);
|
||||
if (child.getCommand() != null) {
|
||||
contextBuilder.withCommand(child.getCommand());
|
||||
}
|
||||
node = child;
|
||||
break;
|
||||
} catch (IllegalArgumentSyntaxException ex) {
|
||||
exception = ex;
|
||||
for (CommandNode child : node.getChildren()) {
|
||||
try {
|
||||
CommandContextBuilder context = contextBuilder.copy();
|
||||
String remaining = child.parse(command, context);
|
||||
if (child.getCommand() != null) {
|
||||
context.withCommand(child.getCommand());
|
||||
}
|
||||
}
|
||||
|
||||
if (exception != null) {
|
||||
break;
|
||||
return parseNodes(child, remaining, context);
|
||||
} catch (IllegalArgumentSyntaxException ex) {
|
||||
exception = ex;
|
||||
}
|
||||
}
|
||||
|
||||
if (exception != null) {
|
||||
throw exception;
|
||||
}
|
||||
if (command.length() > 0) {
|
||||
throw new UnknownCommandException();
|
||||
}
|
||||
|
||||
CommandContext context = contextBuilder.build();
|
||||
context.getCommand().run(context);
|
||||
return contextBuilder.build();
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
|
|
@ -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())
|
||||
|
|
Loading…
Reference in a new issue