Added a 'source' for commands that may be passed around in the context

This commit is contained in:
Nathan Adams 2014-09-29 12:18:40 +02:00
parent 6a8d067cf9
commit 2114f086cb
10 changed files with 60 additions and 41 deletions

View file

@ -10,7 +10,7 @@ import net.minecraft.commands.exceptions.UnknownCommandException;
import net.minecraft.commands.tree.CommandNode;
import net.minecraft.commands.tree.RootCommandNode;
public class CommandDispatcher {
public class CommandDispatcher<T> {
public static final String ARGUMENT_SEPARATOR = " ";
private final RootCommandNode root = new RootCommandNode();
@ -19,17 +19,17 @@ public class CommandDispatcher {
root.addChild(command.build());
}
public void execute(String command) throws CommandException {
CommandContext context = parseNodes(root, command, new CommandContextBuilder());
public void execute(String command, T source) throws CommandException {
CommandContext<T> context = parseNodes(root, command, new CommandContextBuilder<T>(source));
context.getCommand().run(context);
}
protected CommandContext parseNodes(CommandNode node, String command, CommandContextBuilder contextBuilder) throws IllegalArgumentSyntaxException, ArgumentValidationException, UnknownCommandException {
protected CommandContext<T> parseNodes(CommandNode node, String command, CommandContextBuilder<T> contextBuilder) throws IllegalArgumentSyntaxException, ArgumentValidationException, UnknownCommandException {
IllegalArgumentSyntaxException exception = null;
for (CommandNode child : node.getChildren()) {
try {
CommandContextBuilder context = contextBuilder.copy();
CommandContextBuilder<T> context = contextBuilder.copy();
String remaining = child.parse(command, context);
if (child.getCommand() != null) {
context.withCommand(child.getCommand());

View file

@ -30,7 +30,7 @@ public class IntegerArgumentType implements CommandArgumentType<Integer> {
return new IntegerArgumentType(min, max);
}
public static int getInteger(CommandContext context, String name) {
public static int getInteger(CommandContext<?> context, String name) {
return context.getArgument(name, int.class).getResult();
}

View file

@ -5,11 +5,13 @@ import net.minecraft.commands.Command;
import java.util.Map;
public class CommandContext {
public class CommandContext<T> {
private final T source;
private final Map<String, ParsedArgument<?>> arguments;
private final Command command;
public CommandContext(Map<String, ParsedArgument<?>> arguments, Command command) {
public CommandContext(T source, Map<String, ParsedArgument<?>> arguments, Command command) {
this.source = source;
this.arguments = arguments;
this.command = command;
}
@ -18,8 +20,12 @@ public class CommandContext {
return command;
}
public T getSource() {
return source;
}
@SuppressWarnings("unchecked")
public <T> ParsedArgument<T> getArgument(String name, Class<T> clazz) {
public <V> ParsedArgument<V> getArgument(String name, Class<V> clazz) {
ParsedArgument<?> argument = arguments.get(name);
if (argument == null) {
@ -27,7 +33,7 @@ public class CommandContext {
}
if (Primitives.wrap(clazz).isAssignableFrom(argument.getResult().getClass())) {
return (ParsedArgument<T>) argument;
return (ParsedArgument<V>) argument;
} else {
throw new IllegalArgumentException("Argument '" + name + "' is defined as " + argument.getResult().getClass().getSimpleName() + ", not " + clazz);
}

View file

@ -5,14 +5,16 @@ import net.minecraft.commands.Command;
import java.util.Map;
public class CommandContextBuilder {
public class CommandContextBuilder<T> {
private final Map<String, ParsedArgument<?>> arguments = Maps.newHashMap();
private final T source;
private Command command;
public CommandContextBuilder() {
public CommandContextBuilder(T source) {
this.source = source;
}
public CommandContextBuilder withArgument(String name, ParsedArgument<?> argument) {
public CommandContextBuilder<T> withArgument(String name, ParsedArgument<?> argument) {
this.arguments.put(name, argument);
return this;
}
@ -21,19 +23,19 @@ public class CommandContextBuilder {
return arguments;
}
public CommandContextBuilder withCommand(Command command) {
public CommandContextBuilder<T> withCommand(Command command) {
this.command = command;
return this;
}
public CommandContextBuilder copy() {
CommandContextBuilder copy = new CommandContextBuilder();
public CommandContextBuilder<T> copy() {
CommandContextBuilder<T> copy = new CommandContextBuilder<T>(source);
copy.command = this.command;
copy.arguments.putAll(this.arguments);
return copy;
}
public CommandContext build() {
return new CommandContext(arguments, command);
public CommandContext<T> build() {
return new CommandContext<T>(source, arguments, command);
}
}

View file

@ -19,19 +19,20 @@ import static org.mockito.Mockito.verify;
@RunWith(MockitoJUnitRunner.class)
public class CommandDispatcherTest {
CommandDispatcher subject;
CommandDispatcher<Object> subject;
@Mock Command command;
@Mock Object source;
@Before
public void setUp() throws Exception {
subject = new CommandDispatcher();
subject = new CommandDispatcher<Object>();
}
@Test
public void testCreateAndExecuteCommand() throws Exception {
subject.register(literal("foo").executes(command));
subject.execute("foo");
subject.execute("foo", source);
verify(command).run(any(CommandContext.class));
}
@ -40,8 +41,8 @@ public class CommandDispatcherTest {
subject.register(literal("base").then(literal("foo")).executes(command));
subject.register(literal("base").then(literal("bar")).executes(command));
subject.execute("base foo");
subject.execute("base bar");
subject.execute("base foo", source);
subject.execute("base bar", source);
verify(command, times(2)).run(any(CommandContext.class));
}
@ -67,25 +68,25 @@ public class CommandDispatcherTest {
)
);
subject.execute("foo 1 one");
subject.execute("foo 1 one", source);
verify(one).run(any(CommandContext.class));
subject.execute("foo 2 two");
subject.execute("foo 2 two", source);
verify(two).run(any(CommandContext.class));
subject.execute("foo 3 three");
subject.execute("foo 3 three", source);
verify(three).run(any(CommandContext.class));
}
@Test(expected = UnknownCommandException.class)
public void testExecuteUnknownCommand() throws Exception {
subject.execute("foo");
subject.execute("foo", source);
}
@Test(expected = UnknownCommandException.class)
public void testExecuteUnknownSubcommand() throws Exception {
subject.register(literal("foo").executes(command));
subject.execute("foo bar");
subject.execute("foo bar", source);
}
@Test
@ -100,7 +101,7 @@ public class CommandDispatcherTest {
literal("c")
).executes(command));
subject.execute("foo b");
subject.execute("foo b", source);
verify(subCommand).run(any(CommandContext.class));
}
@ -110,6 +111,6 @@ public class CommandDispatcherTest {
argument("bar", integer())
).executes(command));
subject.execute("foo bar");
subject.execute("foo bar", source);
}
}

View file

@ -63,7 +63,7 @@ public class IntegerArgumentTypeTest {
@Test
public void testGetInteger() throws Exception {
CommandContext context = new CommandContextBuilder().withArgument("foo", type.parse("100")).build();
CommandContext context = new CommandContextBuilder<Object>(new Object()).withArgument("foo", type.parse("100")).build();
assertThat(IntegerArgumentType.getInteger(context, "foo"), is(100));
}

View file

@ -3,32 +3,42 @@ package net.minecraft.commands.context;
import net.minecraft.commands.arguments.IntegerArgumentType;
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.mockito.Mock;
import org.mockito.runners.MockitoJUnitRunner;
import static org.hamcrest.Matchers.is;
import static org.junit.Assert.assertThat;
@RunWith(MockitoJUnitRunner.class)
public class CommandContextTest {
CommandContext context;
CommandContextBuilder<Object> builder;
@Mock Object source;
@Before
public void setUp() throws Exception {
context = new CommandContextBuilder().build();
builder = new CommandContextBuilder<Object>(source);
}
@Test(expected = IllegalArgumentException.class)
public void testGetArgument_nonexistent() throws Exception {
context.getArgument("foo", Object.class);
builder.build().getArgument("foo", Object.class);
}
@Test(expected = IllegalArgumentException.class)
public void testGetArgument_wrongType() throws Exception {
context = new CommandContextBuilder().withArgument("foo", IntegerArgumentType.integer().parse("123")).build();
CommandContext<Object> context = builder.withArgument("foo", IntegerArgumentType.integer().parse("123")).build();
context.getArgument("foo", String.class);
}
@Test
public void testGetArgument() throws Exception {
context = new CommandContextBuilder().withArgument("foo", IntegerArgumentType.integer().parse("123")).build();
CommandContext<Object> context = builder.withArgument("foo", IntegerArgumentType.integer().parse("123")).build();
assertThat(context.getArgument("foo", int.class).getResult(), is(123));
}
@Test
public void testSource() throws Exception {
assertThat(builder.build().getSource(), is(source));
}
}

View file

@ -15,7 +15,7 @@ import static org.mockito.Mockito.mock;
public class ArgumentCommandNodeTest extends AbstractCommandNodeTest {
ArgumentCommandNode node;
CommandContextBuilder contextBuilder;
CommandContextBuilder<Object> contextBuilder;
@Override
protected CommandNode getCommandNode() {
@ -25,7 +25,7 @@ public class ArgumentCommandNodeTest extends AbstractCommandNodeTest {
@Before
public void setUp() throws Exception {
node = argument("foo", integer()).build();
contextBuilder = new CommandContextBuilder();
contextBuilder = new CommandContextBuilder<Object>(new Object());
}
@Test

View file

@ -14,7 +14,7 @@ import static org.mockito.Mockito.mock;
public class LiteralCommandNodeTest extends AbstractCommandNodeTest {
LiteralCommandNode node;
CommandContextBuilder contextBuilder;
CommandContextBuilder<Object> contextBuilder;
@Override
protected CommandNode getCommandNode() {
@ -24,7 +24,7 @@ public class LiteralCommandNodeTest extends AbstractCommandNodeTest {
@Before
public void setUp() throws Exception {
node = literal("foo").build();
contextBuilder = new CommandContextBuilder();
contextBuilder = new CommandContextBuilder<Object>(new Object());
}
@Test

View file

@ -24,7 +24,7 @@ public class RootCommandNodeTest extends AbstractCommandNodeTest {
@Test
public void testParse() throws Exception {
assertThat(node.parse("foo bar baz", new CommandContextBuilder()), is("foo bar baz"));
assertThat(node.parse("foo bar baz", new CommandContextBuilder<Object>(new Object())), is("foo bar baz"));
}
@Test(expected = UnsupportedOperationException.class)