Always try every route to find a matching command
This commit is contained in:
@@ -3,6 +3,7 @@ package net.minecraft.commands;
|
|||||||
import net.minecraft.commands.builder.LiteralArgumentBuilder;
|
import net.minecraft.commands.builder.LiteralArgumentBuilder;
|
||||||
import net.minecraft.commands.context.CommandContext;
|
import net.minecraft.commands.context.CommandContext;
|
||||||
import net.minecraft.commands.context.CommandContextBuilder;
|
import net.minecraft.commands.context.CommandContextBuilder;
|
||||||
|
import net.minecraft.commands.exceptions.ArgumentValidationException;
|
||||||
import net.minecraft.commands.exceptions.CommandException;
|
import net.minecraft.commands.exceptions.CommandException;
|
||||||
import net.minecraft.commands.exceptions.IllegalArgumentSyntaxException;
|
import net.minecraft.commands.exceptions.IllegalArgumentSyntaxException;
|
||||||
import net.minecraft.commands.exceptions.UnknownCommandException;
|
import net.minecraft.commands.exceptions.UnknownCommandException;
|
||||||
@@ -19,35 +20,33 @@ public class CommandDispatcher {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public void execute(String command) throws CommandException {
|
public void execute(String command) throws CommandException {
|
||||||
CommandContextBuilder contextBuilder = new CommandContextBuilder();
|
CommandContext context = parseNodes(root, command, new CommandContextBuilder());
|
||||||
CommandNode node = root;
|
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;
|
IllegalArgumentSyntaxException exception = null;
|
||||||
|
|
||||||
for (CommandNode child : node.getChildren()) {
|
for (CommandNode child : node.getChildren()) {
|
||||||
try {
|
try {
|
||||||
command = child.parse(command, contextBuilder);
|
CommandContextBuilder context = contextBuilder.copy();
|
||||||
if (child.getCommand() != null) {
|
String remaining = child.parse(command, context);
|
||||||
contextBuilder.withCommand(child.getCommand());
|
if (child.getCommand() != null) {
|
||||||
}
|
context.withCommand(child.getCommand());
|
||||||
node = child;
|
|
||||||
break;
|
|
||||||
} catch (IllegalArgumentSyntaxException ex) {
|
|
||||||
exception = ex;
|
|
||||||
}
|
}
|
||||||
}
|
return parseNodes(child, remaining, context);
|
||||||
|
} catch (IllegalArgumentSyntaxException ex) {
|
||||||
if (exception != null) {
|
exception = ex;
|
||||||
break;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (exception != null) {
|
||||||
|
throw exception;
|
||||||
|
}
|
||||||
if (command.length() > 0) {
|
if (command.length() > 0) {
|
||||||
throw new UnknownCommandException();
|
throw new UnknownCommandException();
|
||||||
}
|
}
|
||||||
|
|
||||||
CommandContext context = contextBuilder.build();
|
return contextBuilder.build();
|
||||||
context.getCommand().run(context);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -26,6 +26,13 @@ public class CommandContextBuilder {
|
|||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public CommandContextBuilder copy() {
|
||||||
|
CommandContextBuilder copy = new CommandContextBuilder();
|
||||||
|
copy.command = this.command;
|
||||||
|
copy.arguments.putAll(this.arguments);
|
||||||
|
return copy;
|
||||||
|
}
|
||||||
|
|
||||||
public CommandContext build() {
|
public CommandContext build() {
|
||||||
return new CommandContext(arguments, command);
|
return new CommandContext(arguments, command);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,6 +1,7 @@
|
|||||||
package net.minecraft.commands;
|
package net.minecraft.commands;
|
||||||
|
|
||||||
import net.minecraft.commands.context.CommandContext;
|
import net.minecraft.commands.context.CommandContext;
|
||||||
|
import net.minecraft.commands.exceptions.IllegalArgumentSyntaxException;
|
||||||
import net.minecraft.commands.exceptions.UnknownCommandException;
|
import net.minecraft.commands.exceptions.UnknownCommandException;
|
||||||
import org.junit.Before;
|
import org.junit.Before;
|
||||||
import org.junit.Test;
|
import org.junit.Test;
|
||||||
@@ -44,6 +45,38 @@ public class CommandDispatcherTest {
|
|||||||
verify(command, times(2)).run(any(CommandContext.class));
|
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)
|
@Test(expected = UnknownCommandException.class)
|
||||||
public void testExecuteUnknownCommand() throws Exception {
|
public void testExecuteUnknownCommand() throws Exception {
|
||||||
subject.execute("foo");
|
subject.execute("foo");
|
||||||
@@ -71,7 +104,7 @@ public class CommandDispatcherTest {
|
|||||||
verify(subCommand).run(any(CommandContext.class));
|
verify(subCommand).run(any(CommandContext.class));
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test(expected = UnknownCommandException.class)
|
@Test(expected = IllegalArgumentSyntaxException.class)
|
||||||
public void testExecuteInvalidSubcommand() throws Exception {
|
public void testExecuteInvalidSubcommand() throws Exception {
|
||||||
subject.register(literal("foo").then(
|
subject.register(literal("foo").then(
|
||||||
argument("bar", integer())
|
argument("bar", integer())
|
||||||
|
|||||||
Reference in New Issue
Block a user