mirror of
https://github.com/SquidDev-CC/CC-Tweaked
synced 2025-11-13 03:43:08 +00:00
Rewrite computer selectors
This adds support for computer selectors, in the style of entity selectors. The long-term goal here is to replace our existing ad-hoc selectors. However, to aid migration, we currently support both - the previous one will most likely be removed in MC 1.21. Computer selectors take the form @c[<key>=<value>,...]. Currently we support filtering by id, instance id, label, family (as before) and distance from the player (new!). The code also supports computers within a bounding box, but there's no parsing support for that yet. This commit also (finally) documents the /computercraft command. Well, sort of - it's definitely not my best word, but I couldn't find better words.
This commit is contained in:
@@ -0,0 +1,90 @@
|
||||
// SPDX-FileCopyrightText: 2023 The CC: Tweaked Developers
|
||||
//
|
||||
// SPDX-License-Identifier: MPL-2.0
|
||||
|
||||
package dan200.computercraft.shared.command.arguments;
|
||||
|
||||
import com.mojang.brigadier.StringReader;
|
||||
import com.mojang.brigadier.context.CommandContext;
|
||||
import com.mojang.brigadier.context.StringRange;
|
||||
import com.mojang.brigadier.exceptions.CommandSyntaxException;
|
||||
import com.mojang.brigadier.suggestion.Suggestion;
|
||||
import com.mojang.brigadier.suggestion.SuggestionsBuilder;
|
||||
import dan200.computercraft.shared.command.Exceptions;
|
||||
import dan200.computercraft.shared.computer.core.ComputerFamily;
|
||||
import dan200.computercraft.test.core.ReplaceUnderscoresDisplayNameGenerator;
|
||||
import org.junit.jupiter.api.DisplayNameGeneration;
|
||||
import org.junit.jupiter.api.Test;
|
||||
import org.junit.jupiter.params.ParameterizedTest;
|
||||
import org.junit.jupiter.params.provider.Arguments;
|
||||
import org.junit.jupiter.params.provider.MethodSource;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.OptionalInt;
|
||||
|
||||
import static org.hamcrest.MatcherAssert.assertThat;
|
||||
import static org.hamcrest.Matchers.*;
|
||||
import static org.junit.jupiter.api.Assertions.assertEquals;
|
||||
import static org.junit.jupiter.api.Assertions.assertThrows;
|
||||
|
||||
@DisplayNameGeneration(ReplaceUnderscoresDisplayNameGenerator.class)
|
||||
class ComputerSelectorTest {
|
||||
@ParameterizedTest(name = "{0}")
|
||||
@MethodSource("getArgumentTestCases")
|
||||
public void Parse_basic_inputs(String input, ComputerSelector expected) throws CommandSyntaxException {
|
||||
assertEquals(expected, ComputerSelector.parse(new StringReader(input)));
|
||||
}
|
||||
|
||||
public static Arguments[] getArgumentTestCases() {
|
||||
return new Arguments[]{
|
||||
// Legacy selectors
|
||||
Arguments.of("@some_label", new ComputerSelector("@some_label", OptionalInt.empty(), OptionalInt.empty(), "some_label", null, null, null)),
|
||||
Arguments.of("~normal", new ComputerSelector("~normal", OptionalInt.empty(), OptionalInt.empty(), null, ComputerFamily.NORMAL, null, null)),
|
||||
Arguments.of("#123", new ComputerSelector("#123", OptionalInt.empty(), OptionalInt.of(123), null, null, null, null)),
|
||||
Arguments.of("123", new ComputerSelector("123", OptionalInt.of(123), OptionalInt.empty(), null, null, null, null)),
|
||||
// New selectors
|
||||
Arguments.of("@c[]", new ComputerSelector("@c[]", OptionalInt.empty(), OptionalInt.empty(), null, null, null, null)),
|
||||
Arguments.of("@c[instance=123]", new ComputerSelector("@c[instance=123]", OptionalInt.of(123), OptionalInt.empty(), null, null, null, null)),
|
||||
Arguments.of("@c[id=123]", new ComputerSelector("@c[id=123]", OptionalInt.empty(), OptionalInt.of(123), null, null, null, null)),
|
||||
Arguments.of("@c[label=\"foo\"]", new ComputerSelector("@c[label=\"foo\"]", OptionalInt.empty(), OptionalInt.empty(), "foo", null, null, null)),
|
||||
Arguments.of("@c[family=normal]", new ComputerSelector("@c[family=normal]", OptionalInt.empty(), OptionalInt.empty(), null, ComputerFamily.NORMAL, null, null)),
|
||||
// Complex selectors
|
||||
Arguments.of("@c[ id = 123 , ]", new ComputerSelector("@c[ id = 123 , ]", OptionalInt.empty(), OptionalInt.of(123), null, null, null, null)),
|
||||
Arguments.of("@c[id=123,family=normal]", new ComputerSelector("@c[id=123,family=normal]", OptionalInt.empty(), OptionalInt.of(123), null, ComputerFamily.NORMAL, null, null)),
|
||||
};
|
||||
}
|
||||
|
||||
@Test
|
||||
public void Fails_on_repeated_options() {
|
||||
var error = assertThrows(CommandSyntaxException.class, () -> ComputerSelector.parse(new StringReader("@c[id=1, id=2]")));
|
||||
assertEquals(Exceptions.ERROR_INAPPLICABLE_OPTION, error.getType());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void Complete_selector_components() {
|
||||
assertEquals(List.of(new Suggestion(StringRange.between(0, 1), "@c[")), suggest("@"));
|
||||
assertThat(suggest("@c["), hasItem(
|
||||
new Suggestion(StringRange.at(3), "family", ComputerSelector.options().get("family").tooltip())
|
||||
));
|
||||
assertEquals(List.of(new Suggestion(StringRange.at(9), "=")), suggest("@c[family"));
|
||||
assertEquals(List.of(new Suggestion(StringRange.at(16), ",")), suggest("@c[family=normal"));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void Complete_selector_family() {
|
||||
assertThat(suggest("@c[family="), containsInAnyOrder(
|
||||
new Suggestion(StringRange.at(10), "normal"),
|
||||
new Suggestion(StringRange.at(10), "advanced"),
|
||||
new Suggestion(StringRange.at(10), "command")
|
||||
));
|
||||
assertThat(suggest("@c[family=n"), contains(
|
||||
new Suggestion(StringRange.between(10, 11), "normal")
|
||||
));
|
||||
}
|
||||
|
||||
private List<Suggestion> suggest(String input) {
|
||||
var context = new CommandContext<>(new Object(), "", Map.of(), null, null, List.of(), StringRange.at(0), null, null, false);
|
||||
return ComputerSelector.suggest(context, new SuggestionsBuilder(input, 0)).getNow(null).getList();
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user