EntitySelectorOptions.java
net.minecraft.commands.arguments.selector.options.EntitySelectorOptions
信息
- 全限定名:net.minecraft.commands.arguments.selector.options.EntitySelectorOptions
- 类型:public class
- 包:net.minecraft.commands.arguments.selector.options
- 源码路径:src/main/java/net/minecraft/commands/arguments/selector/options/EntitySelectorOptions.java
- 起始行号:L54
- 职责:
TODO
字段/常量
-
LOGGER- 类型:
Logger - 修饰符:
private static final - 源码定位:
L55 - 说明:
TODO
- 类型:
-
OPTIONS- 类型:
Map<String,EntitySelectorOptions.Option> - 修饰符:
private static final - 源码定位:
L56 - 说明:
TODO
- 类型:
-
ERROR_UNKNOWN_OPTION- 类型:
DynamicCommandExceptionType - 修饰符:
public static final - 源码定位:
L57 - 说明:
TODO
- 类型:
-
ERROR_INAPPLICABLE_OPTION- 类型:
DynamicCommandExceptionType - 修饰符:
public static final - 源码定位:
L60 - 说明:
TODO
- 类型:
-
ERROR_RANGE_NEGATIVE- 类型:
SimpleCommandExceptionType - 修饰符:
public static final - 源码定位:
L63 - 说明:
TODO
- 类型:
-
ERROR_LEVEL_NEGATIVE- 类型:
SimpleCommandExceptionType - 修饰符:
public static final - 源码定位:
L66 - 说明:
TODO
- 类型:
-
ERROR_LIMIT_TOO_SMALL- 类型:
SimpleCommandExceptionType - 修饰符:
public static final - 源码定位:
L69 - 说明:
TODO
- 类型:
-
ERROR_SORT_UNKNOWN- 类型:
DynamicCommandExceptionType - 修饰符:
public static final - 源码定位:
L72 - 说明:
TODO
- 类型:
-
ERROR_GAME_MODE_INVALID- 类型:
DynamicCommandExceptionType - 修饰符:
public static final - 源码定位:
L75 - 说明:
TODO
- 类型:
-
ERROR_ENTITY_TYPE_INVALID- 类型:
DynamicCommandExceptionType - 修饰符:
public static final - 源码定位:
L78 - 说明:
TODO
- 类型:
内部类/嵌套类型
-
net.minecraft.commands.arguments.selector.options.EntitySelectorOptions.Modifier- 类型:
interface - 修饰符:
public - 源码定位:
L522 - 说明:
TODO
- 类型:
-
net.minecraft.commands.arguments.selector.options.EntitySelectorOptions.Option- 类型:
record - 修饰符:
private - 源码定位:
L526 - 说明:
TODO
- 类型:
构造器
- 无
方法
下面的方法块按源码顺序生成。
private static void register(String name, EntitySelectorOptions.Modifier modifier, Predicate<EntitySelectorParser> predicate, Component description) @ L82
- 方法名:register
- 源码定位:L82
- 返回类型:void
- 修饰符:private static
参数:
- name: String
- modifier: EntitySelectorOptions.Modifier
- predicate: Predicate
- description: Component
说明:
TODO
public static void bootStrap() @ L86
- 方法名:bootStrap
- 源码定位:L86
- 返回类型:void
- 修饰符:public static
参数:
- 无
说明:
TODO
public static EntitySelectorOptions.Modifier get(EntitySelectorParser parser, String key, int start) @ L497
- 方法名:get
- 源码定位:L497
- 返回类型:EntitySelectorOptions.Modifier
- 修饰符:public static
参数:
- parser: EntitySelectorParser
- key: String
- start: int
说明:
TODO
public static void suggestNames(EntitySelectorParser parser, SuggestionsBuilder builder) @ L511
- 方法名:suggestNames
- 源码定位:L511
- 返回类型:void
- 修饰符:public static
参数:
- parser: EntitySelectorParser
- builder: SuggestionsBuilder
说明:
TODO
代码
public class EntitySelectorOptions {
private static final Logger LOGGER = LogUtils.getLogger();
private static final Map<String, EntitySelectorOptions.Option> OPTIONS = Maps.newHashMap();
public static final DynamicCommandExceptionType ERROR_UNKNOWN_OPTION = new DynamicCommandExceptionType(
name -> Component.translatableEscape("argument.entity.options.unknown", name)
);
public static final DynamicCommandExceptionType ERROR_INAPPLICABLE_OPTION = new DynamicCommandExceptionType(
name -> Component.translatableEscape("argument.entity.options.inapplicable", name)
);
public static final SimpleCommandExceptionType ERROR_RANGE_NEGATIVE = new SimpleCommandExceptionType(
Component.translatable("argument.entity.options.distance.negative")
);
public static final SimpleCommandExceptionType ERROR_LEVEL_NEGATIVE = new SimpleCommandExceptionType(
Component.translatable("argument.entity.options.level.negative")
);
public static final SimpleCommandExceptionType ERROR_LIMIT_TOO_SMALL = new SimpleCommandExceptionType(
Component.translatable("argument.entity.options.limit.toosmall")
);
public static final DynamicCommandExceptionType ERROR_SORT_UNKNOWN = new DynamicCommandExceptionType(
name -> Component.translatableEscape("argument.entity.options.sort.irreversible", name)
);
public static final DynamicCommandExceptionType ERROR_GAME_MODE_INVALID = new DynamicCommandExceptionType(
name -> Component.translatableEscape("argument.entity.options.mode.invalid", name)
);
public static final DynamicCommandExceptionType ERROR_ENTITY_TYPE_INVALID = new DynamicCommandExceptionType(
type -> Component.translatableEscape("argument.entity.options.type.invalid", type)
);
private static void register(String name, EntitySelectorOptions.Modifier modifier, Predicate<EntitySelectorParser> predicate, Component description) {
OPTIONS.put(name, new EntitySelectorOptions.Option(modifier, predicate, description));
}
public static void bootStrap() {
if (OPTIONS.isEmpty()) {
register("name", parser -> {
int start = parser.getReader().getCursor();
boolean not = parser.shouldInvertValue();
String name = parser.getReader().readString();
if (parser.hasNameNotEquals() && !not) {
parser.getReader().setCursor(start);
throw ERROR_INAPPLICABLE_OPTION.createWithContext(parser.getReader(), "name");
} else {
if (not) {
parser.setHasNameNotEquals(true);
} else {
parser.setHasNameEquals(true);
}
parser.addPredicate(e -> e.getPlainTextName().equals(name) != not);
}
}, s -> !s.hasNameEquals(), Component.translatable("argument.entity.options.name.description"));
register("distance", parser -> {
int start = parser.getReader().getCursor();
MinMaxBounds.Doubles value = MinMaxBounds.Doubles.fromReader(parser.getReader());
if ((!value.min().isPresent() || !((Double)value.min().get() < 0.0)) && (!value.max().isPresent() || !((Double)value.max().get() < 0.0))) {
parser.setDistance(value);
parser.setWorldLimited();
} else {
parser.getReader().setCursor(start);
throw ERROR_RANGE_NEGATIVE.createWithContext(parser.getReader());
}
}, s -> s.getDistance() == null, Component.translatable("argument.entity.options.distance.description"));
register("level", parser -> {
int start = parser.getReader().getCursor();
MinMaxBounds.Ints value = MinMaxBounds.Ints.fromReader(parser.getReader());
if ((!value.min().isPresent() || (Integer)value.min().get() >= 0) && (!value.max().isPresent() || (Integer)value.max().get() >= 0)) {
parser.setLevel(value);
parser.setIncludesEntities(false);
} else {
parser.getReader().setCursor(start);
throw ERROR_LEVEL_NEGATIVE.createWithContext(parser.getReader());
}
}, s -> s.getLevel() == null, Component.translatable("argument.entity.options.level.description"));
register("x", parser -> {
parser.setWorldLimited();
parser.setX(parser.getReader().readDouble());
}, s -> s.getX() == null, Component.translatable("argument.entity.options.x.description"));
register("y", parser -> {
parser.setWorldLimited();
parser.setY(parser.getReader().readDouble());
}, s -> s.getY() == null, Component.translatable("argument.entity.options.y.description"));
register("z", parser -> {
parser.setWorldLimited();
parser.setZ(parser.getReader().readDouble());
}, s -> s.getZ() == null, Component.translatable("argument.entity.options.z.description"));
register("dx", parser -> {
parser.setWorldLimited();
parser.setDeltaX(parser.getReader().readDouble());
}, s -> s.getDeltaX() == null, Component.translatable("argument.entity.options.dx.description"));
register("dy", parser -> {
parser.setWorldLimited();
parser.setDeltaY(parser.getReader().readDouble());
}, s -> s.getDeltaY() == null, Component.translatable("argument.entity.options.dy.description"));
register("dz", parser -> {
parser.setWorldLimited();
parser.setDeltaZ(parser.getReader().readDouble());
}, s -> s.getDeltaZ() == null, Component.translatable("argument.entity.options.dz.description"));
register(
"x_rotation",
parser -> parser.setRotX(MinMaxBounds.FloatDegrees.fromReader(parser.getReader())),
s -> s.getRotX() == null,
Component.translatable("argument.entity.options.x_rotation.description")
);
register(
"y_rotation",
parser -> parser.setRotY(MinMaxBounds.FloatDegrees.fromReader(parser.getReader())),
s -> s.getRotY() == null,
Component.translatable("argument.entity.options.y_rotation.description")
);
register("limit", parser -> {
int start = parser.getReader().getCursor();
int count = parser.getReader().readInt();
if (count < 1) {
parser.getReader().setCursor(start);
throw ERROR_LIMIT_TOO_SMALL.createWithContext(parser.getReader());
} else {
parser.setMaxResults(count);
parser.setLimited(true);
}
}, s -> !s.isCurrentEntity() && !s.isLimited(), Component.translatable("argument.entity.options.limit.description"));
register("sort", parser -> {
int start = parser.getReader().getCursor();
String name = parser.getReader().readUnquotedString();
parser.setSuggestions((b, n) -> SharedSuggestionProvider.suggest(Arrays.asList("nearest", "furthest", "random", "arbitrary"), b));
parser.setOrder(switch (name) {
case "nearest" -> EntitySelectorParser.ORDER_NEAREST;
case "furthest" -> EntitySelectorParser.ORDER_FURTHEST;
case "random" -> EntitySelectorParser.ORDER_RANDOM;
case "arbitrary" -> EntitySelector.ORDER_ARBITRARY;
default -> {
parser.getReader().setCursor(start);
throw ERROR_SORT_UNKNOWN.createWithContext(parser.getReader(), name);
}
});
parser.setSorted(true);
}, s -> !s.isCurrentEntity() && !s.isSorted(), Component.translatable("argument.entity.options.sort.description"));
register("gamemode", parser -> {
parser.setSuggestions((b, m) -> {
String prefix = b.getRemaining().toLowerCase(Locale.ROOT);
boolean addNormal = !parser.hasGamemodeNotEquals();
boolean addInverted = true;
if (!prefix.isEmpty()) {
if (prefix.charAt(0) == '!') {
addNormal = false;
prefix = prefix.substring(1);
} else {
addInverted = false;
}
}
for (GameType type : GameType.values()) {
if (type.getName().toLowerCase(Locale.ROOT).startsWith(prefix)) {
if (addInverted) {
b.suggest("!" + type.getName());
}
if (addNormal) {
b.suggest(type.getName());
}
}
}
return b.buildFuture();
});
int start = parser.getReader().getCursor();
boolean inverted = parser.shouldInvertValue();
if (parser.hasGamemodeNotEquals() && !inverted) {
parser.getReader().setCursor(start);
throw ERROR_INAPPLICABLE_OPTION.createWithContext(parser.getReader(), "gamemode");
} else {
String name = parser.getReader().readUnquotedString();
GameType expected = GameType.byName(name, null);
if (expected == null) {
parser.getReader().setCursor(start);
throw ERROR_GAME_MODE_INVALID.createWithContext(parser.getReader(), name);
} else {
parser.setIncludesEntities(false);
parser.addPredicate(e -> {
if (e instanceof ServerPlayer player) {
GameType current = player.gameMode();
return current == expected ^ inverted;
} else {
return false;
}
});
if (inverted) {
parser.setHasGamemodeNotEquals(true);
} else {
parser.setHasGamemodeEquals(true);
}
}
}
}, s -> !s.hasGamemodeEquals(), Component.translatable("argument.entity.options.gamemode.description"));
register("team", parser -> {
boolean inverted = parser.shouldInvertValue();
String expected = parser.getReader().readUnquotedString();
parser.addPredicate(e -> {
Team current = e.getTeam();
String currentName = current == null ? "" : current.getName();
return currentName.equals(expected) != inverted;
});
if (inverted) {
parser.setHasTeamNotEquals(true);
} else {
parser.setHasTeamEquals(true);
}
}, s -> !s.hasTeamEquals(), Component.translatable("argument.entity.options.team.description"));
register(
"type",
parser -> {
parser.setSuggestions(
(b, m) -> {
SharedSuggestionProvider.suggestResource(BuiltInRegistries.ENTITY_TYPE.keySet(), b, String.valueOf('!'));
SharedSuggestionProvider.suggestResource(BuiltInRegistries.ENTITY_TYPE.getTags().map(tag -> tag.key().location()), b, "!#");
if (!parser.isTypeLimitedInversely()) {
SharedSuggestionProvider.suggestResource(BuiltInRegistries.ENTITY_TYPE.keySet(), b);
SharedSuggestionProvider.suggestResource(
BuiltInRegistries.ENTITY_TYPE.getTags().map(tag -> tag.key().location()), b, String.valueOf('#')
);
}
return b.buildFuture();
}
);
int start = parser.getReader().getCursor();
boolean inverted = parser.shouldInvertValue();
if (parser.isTypeLimitedInversely() && !inverted) {
parser.getReader().setCursor(start);
throw ERROR_INAPPLICABLE_OPTION.createWithContext(parser.getReader(), "type");
} else {
if (inverted) {
parser.setTypeLimitedInversely();
}
if (parser.isTag()) {
TagKey<EntityType<?>> id = TagKey.create(Registries.ENTITY_TYPE, Identifier.read(parser.getReader()));
parser.addPredicate(e -> e.is(id) != inverted);
} else {
Identifier id = Identifier.read(parser.getReader());
EntityType<?> type = BuiltInRegistries.ENTITY_TYPE.getOptional(id).orElseThrow(() -> {
parser.getReader().setCursor(start);
return ERROR_ENTITY_TYPE_INVALID.createWithContext(parser.getReader(), id.toString());
});
if (Objects.equals(EntityType.PLAYER, type) && !inverted) {
parser.setIncludesEntities(false);
}
parser.addPredicate(e -> Objects.equals(type, e.getType()) != inverted);
if (!inverted) {
parser.limitToType(type);
}
}
}
},
s -> !s.isTypeLimited(),
Component.translatable("argument.entity.options.type.description")
);
register("tag", parser -> {
boolean inverted = parser.shouldInvertValue();
String tag = parser.getReader().readUnquotedString();
parser.addPredicate(e -> "".equals(tag) ? e.entityTags().isEmpty() != inverted : e.entityTags().contains(tag) != inverted);
}, s -> true, Component.translatable("argument.entity.options.tag.description"));
register("nbt", parser -> {
boolean inverted = parser.shouldInvertValue();
CompoundTag tag = TagParser.parseCompoundAsArgument(parser.getReader());
parser.addPredicate(e -> {
boolean var9;
try (ProblemReporter.ScopedCollector reporter = new ProblemReporter.ScopedCollector(e.problemPath(), LOGGER)) {
TagValueOutput output = TagValueOutput.createWithContext(reporter, e.registryAccess());
e.saveWithoutId(output);
if (e instanceof ServerPlayer player) {
ItemStack selected = player.getInventory().getSelectedItem();
if (!selected.isEmpty()) {
output.store("SelectedItem", ItemStack.CODEC, selected);
}
}
var9 = NbtUtils.compareNbt(tag, output.buildResult(), true) != inverted;
}
return var9;
});
}, s -> true, Component.translatable("argument.entity.options.nbt.description"));
register("scores", parser -> {
StringReader reader = parser.getReader();
Map<String, MinMaxBounds.Ints> expected = Maps.newHashMap();
reader.expect('{');
reader.skipWhitespace();
while (reader.canRead() && reader.peek() != '}') {
reader.skipWhitespace();
String name = reader.readUnquotedString();
reader.skipWhitespace();
reader.expect('=');
reader.skipWhitespace();
MinMaxBounds.Ints value = MinMaxBounds.Ints.fromReader(reader);
expected.put(name, value);
reader.skipWhitespace();
if (reader.canRead() && reader.peek() == ',') {
reader.skip();
}
}
reader.expect('}');
if (!expected.isEmpty()) {
parser.addPredicate(entity -> {
Scoreboard scoreboard = entity.level().getServer().getScoreboard();
for (Entry<String, MinMaxBounds.Ints> entry : expected.entrySet()) {
Objective objective = scoreboard.getObjective(entry.getKey());
if (objective == null) {
return false;
}
ReadOnlyScoreInfo scoreInfo = scoreboard.getPlayerScoreInfo(entity, objective);
if (scoreInfo == null) {
return false;
}
if (!entry.getValue().matches(scoreInfo.value())) {
return false;
}
}
return true;
});
}
parser.setHasScores(true);
}, s -> !s.hasScores(), Component.translatable("argument.entity.options.scores.description"));
register("advancements", parser -> {
StringReader reader = parser.getReader();
Map<Identifier, Predicate<AdvancementProgress>> expected = Maps.newHashMap();
reader.expect('{');
reader.skipWhitespace();
while (reader.canRead() && reader.peek() != '}') {
reader.skipWhitespace();
Identifier name = Identifier.read(reader);
reader.skipWhitespace();
reader.expect('=');
reader.skipWhitespace();
if (reader.canRead() && reader.peek() == '{') {
Map<String, Predicate<CriterionProgress>> progress = Maps.newHashMap();
reader.skipWhitespace();
reader.expect('{');
reader.skipWhitespace();
while (reader.canRead() && reader.peek() != '}') {
reader.skipWhitespace();
String criterion = reader.readUnquotedString();
reader.skipWhitespace();
reader.expect('=');
reader.skipWhitespace();
boolean value = reader.readBoolean();
progress.put(criterion, p -> p.isDone() == value);
reader.skipWhitespace();
if (reader.canRead() && reader.peek() == ',') {
reader.skip();
}
}
reader.skipWhitespace();
reader.expect('}');
reader.skipWhitespace();
expected.put(name, p -> {
for (Entry<String, Predicate<CriterionProgress>> entry : progress.entrySet()) {
CriterionProgress criterionx = p.getCriterion(entry.getKey());
if (criterionx == null || !entry.getValue().test(criterionx)) {
return false;
}
}
return true;
});
} else {
boolean value = reader.readBoolean();
expected.put(name, p -> p.isDone() == value);
}
reader.skipWhitespace();
if (reader.canRead() && reader.peek() == ',') {
reader.skip();
}
}
reader.expect('}');
if (!expected.isEmpty()) {
parser.addPredicate(e -> {
if (!(e instanceof ServerPlayer player)) {
return false;
} else {
PlayerAdvancements advancements = player.getAdvancements();
ServerAdvancementManager serverAdvancements = player.level().getServer().getAdvancements();
for (Entry<Identifier, Predicate<AdvancementProgress>> entry : expected.entrySet()) {
AdvancementHolder advancement = serverAdvancements.get(entry.getKey());
if (advancement == null || !entry.getValue().test(advancements.getOrStartProgress(advancement))) {
return false;
}
}
return true;
}
});
parser.setIncludesEntities(false);
}
parser.setHasAdvancements(true);
}, s -> !s.hasAdvancements(), Component.translatable("argument.entity.options.advancements.description"));
register(
"predicate",
parser -> {
boolean inverted = parser.shouldInvertValue();
ResourceKey<LootItemCondition> id = ResourceKey.create(Registries.PREDICATE, Identifier.read(parser.getReader()));
parser.addPredicate(
entity -> {
if (entity.level() instanceof ServerLevel level) {
Optional<LootItemCondition> condition = level.getServer().reloadableRegistries().lookup().get(id).map(Holder::value);
if (condition.isEmpty()) {
return false;
} else {
LootParams lootParams = new LootParams.Builder(level)
.withParameter(LootContextParams.THIS_ENTITY, entity)
.withParameter(LootContextParams.ORIGIN, entity.position())
.create(LootContextParamSets.SELECTOR);
LootContext context = new LootContext.Builder(lootParams).create(Optional.empty());
context.pushVisitedElement(LootContext.createVisitedEntry(condition.get()));
return inverted ^ condition.get().test(context);
}
} else {
return false;
}
}
);
},
s -> true,
Component.translatable("argument.entity.options.predicate.description")
);
}
}
public static EntitySelectorOptions.Modifier get(EntitySelectorParser parser, String key, int start) throws CommandSyntaxException {
EntitySelectorOptions.Option option = OPTIONS.get(key);
if (option != null) {
if (option.canUse.test(parser)) {
return option.modifier;
} else {
throw ERROR_INAPPLICABLE_OPTION.createWithContext(parser.getReader(), key);
}
} else {
parser.getReader().setCursor(start);
throw ERROR_UNKNOWN_OPTION.createWithContext(parser.getReader(), key);
}
}
public static void suggestNames(EntitySelectorParser parser, SuggestionsBuilder builder) {
String lowerPrefix = builder.getRemaining().toLowerCase(Locale.ROOT);
for (Entry<String, EntitySelectorOptions.Option> entry : OPTIONS.entrySet()) {
if (entry.getValue().canUse.test(parser) && entry.getKey().toLowerCase(Locale.ROOT).startsWith(lowerPrefix)) {
builder.suggest(entry.getKey() + "=", entry.getValue().description);
}
}
}
@FunctionalInterface
public interface Modifier {
void handle(EntitySelectorParser parser) throws CommandSyntaxException;
}
private record Option(EntitySelectorOptions.Modifier modifier, Predicate<EntitySelectorParser> canUse, Component description) {
}
}引用的其他类
-
- 引用位置:
方法调用 - 关联成员:
MinMaxBounds.Doubles.fromReader(), MinMaxBounds.FloatDegrees.fromReader(), MinMaxBounds.Ints.fromReader()
- 引用位置:
-
- 引用位置:
方法调用 - 关联成员:
SharedSuggestionProvider.suggest(), SharedSuggestionProvider.suggestResource()
- 引用位置:
-
- 引用位置:
参数
- 引用位置:
-
- 引用位置:
方法调用 - 关联成员:
NbtUtils.compareNbt()
- 引用位置:
-
- 引用位置:
方法调用 - 关联成员:
TagParser.parseCompoundAsArgument()
- 引用位置:
-
- 引用位置:
参数/方法调用 - 关联成员:
Component.translatable(), Component.translatableEscape()
- 引用位置:
-
- 引用位置:
方法调用 - 关联成员:
Identifier.read()
- 引用位置:
-
- 引用位置:
方法调用 - 关联成员:
ResourceKey.create()
- 引用位置:
-
- 引用位置:
方法调用 - 关联成员:
TagKey.create()
- 引用位置:
-
- 引用位置:
方法调用/构造调用 - 关联成员:
ProblemReporter.ScopedCollector(), ScopedCollector()
- 引用位置:
-
- 引用位置:
方法调用 - 关联成员:
GameType.byName(), GameType.values()
- 引用位置:
-
- 引用位置:
方法调用 - 关联成员:
TagValueOutput.createWithContext()
- 引用位置:
-
- 引用位置:
方法调用/构造调用 - 关联成员:
Builder(), LootContext.Builder(), LootContext.createVisitedEntry()
- 引用位置:
-
- 引用位置:
方法调用/构造调用 - 关联成员:
Builder(), LootParams.Builder()
- 引用位置: