ItemParser.java

net.minecraft.commands.arguments.item.ItemParser

信息

  • 全限定名:net.minecraft.commands.arguments.item.ItemParser
  • 类型:public class
  • 包:net.minecraft.commands.arguments.item
  • 源码路径:src/main/java/net/minecraft/commands/arguments/item/ItemParser.java
  • 起始行号:L34
  • 职责:

    TODO

字段/常量

  • ERROR_UNKNOWN_ITEM

    • 类型: DynamicCommandExceptionType
    • 修饰符: private static final
    • 源码定位: L35
    • 说明:

      TODO

  • ERROR_UNKNOWN_COMPONENT

    • 类型: DynamicCommandExceptionType
    • 修饰符: private static final
    • 源码定位: L38
    • 说明:

      TODO

  • ERROR_MALFORMED_COMPONENT

    • 类型: Dynamic2CommandExceptionType
    • 修饰符: private static final
    • 源码定位: L41
    • 说明:

      TODO

  • ERROR_EXPECTED_COMPONENT

    • 类型: SimpleCommandExceptionType
    • 修饰符: private static final
    • 源码定位: L44
    • 说明:

      TODO

  • ERROR_REPEATED_COMPONENT

    • 类型: DynamicCommandExceptionType
    • 修饰符: private static final
    • 源码定位: L47
    • 说明:

      TODO

  • SYNTAX_START_COMPONENTS

    • 类型: char
    • 修饰符: public static final
    • 源码定位: L50
    • 说明:

      TODO

  • SYNTAX_END_COMPONENTS

    • 类型: char
    • 修饰符: public static final
    • 源码定位: L51
    • 说明:

      TODO

  • SYNTAX_COMPONENT_SEPARATOR

    • 类型: char
    • 修饰符: public static final
    • 源码定位: L52
    • 说明:

      TODO

  • SYNTAX_COMPONENT_ASSIGNMENT

    • 类型: char
    • 修饰符: public static final
    • 源码定位: L53
    • 说明:

      TODO

  • SYNTAX_REMOVED_COMPONENT

    • 类型: char
    • 修饰符: public static final
    • 源码定位: L54
    • 说明:

      TODO

  • SUGGEST_NOTHING

    • 类型: Function<SuggestionsBuilder,CompletableFuture<Suggestions>>
    • 修饰符: private static final
    • 源码定位: L55
    • 说明:

      TODO

  • items

    • 类型: HolderLookup.RegistryLookup<Item>
    • 修饰符: private final
    • 源码定位: L56
    • 说明:

      TODO

  • registryOps

    • 类型: RegistryOps<Tag>
    • 修饰符: private final
    • 源码定位: L57
    • 说明:

      TODO

  • tagParser

    • 类型: TagParser<Tag>
    • 修饰符: private final
    • 源码定位: L58
    • 说明:

      TODO

内部类/嵌套类型

  • net.minecraft.commands.arguments.item.ItemParser.State

    • 类型: class
    • 修饰符: private
    • 源码定位: L119
    • 说明:

      TODO

  • net.minecraft.commands.arguments.item.ItemParser.SuggestionsVisitor

    • 类型: class
    • 修饰符: private static
    • 源码定位: L278
    • 说明:

      TODO

  • net.minecraft.commands.arguments.item.ItemParser.Visitor

    • 类型: interface
    • 修饰符: public
    • 源码定位: L291
    • 说明:

      TODO

构造器

public ItemParser(HolderLookup.Provider registries) @ L60

  • 构造器名:ItemParser
  • 源码定位:L60
  • 修饰符:public

参数:

  • registries: HolderLookup.Provider

说明:

TODO

方法

下面的方法块按源码顺序生成。

public ItemInput parse(StringReader reader) @ L66

  • 方法名:parse
  • 源码定位:L66
  • 返回类型:ItemInput
  • 修饰符:public

参数:

  • reader: StringReader

说明:

TODO

public void parse(StringReader reader, ItemParser.Visitor visitor) @ L94

  • 方法名:parse
  • 源码定位:L94
  • 返回类型:void
  • 修饰符:public

参数:

  • reader: StringReader
  • visitor: ItemParser.Visitor

说明:

TODO

public CompletableFuture<Suggestions> fillSuggestions(SuggestionsBuilder builder) @ L105

  • 方法名:fillSuggestions
  • 源码定位:L105
  • 返回类型:CompletableFuture
  • 修饰符:public

参数:

  • builder: SuggestionsBuilder

说明:

TODO

代码

public class ItemParser {
    private static final DynamicCommandExceptionType ERROR_UNKNOWN_ITEM = new DynamicCommandExceptionType(
        id -> Component.translatableEscape("argument.item.id.invalid", id)
    );
    private static final DynamicCommandExceptionType ERROR_UNKNOWN_COMPONENT = new DynamicCommandExceptionType(
        id -> Component.translatableEscape("arguments.item.component.unknown", id)
    );
    private static final Dynamic2CommandExceptionType ERROR_MALFORMED_COMPONENT = new Dynamic2CommandExceptionType(
        (type, message) -> Component.translatableEscape("arguments.item.component.malformed", type, message)
    );
    private static final SimpleCommandExceptionType ERROR_EXPECTED_COMPONENT = new SimpleCommandExceptionType(
        Component.translatable("arguments.item.component.expected")
    );
    private static final DynamicCommandExceptionType ERROR_REPEATED_COMPONENT = new DynamicCommandExceptionType(
        id -> Component.translatableEscape("arguments.item.component.repeated", id)
    );
    public static final char SYNTAX_START_COMPONENTS = '[';
    public static final char SYNTAX_END_COMPONENTS = ']';
    public static final char SYNTAX_COMPONENT_SEPARATOR = ',';
    public static final char SYNTAX_COMPONENT_ASSIGNMENT = '=';
    public static final char SYNTAX_REMOVED_COMPONENT = '!';
    private static final Function<SuggestionsBuilder, CompletableFuture<Suggestions>> SUGGEST_NOTHING = SuggestionsBuilder::buildFuture;
    private final HolderLookup.RegistryLookup<Item> items;
    private final RegistryOps<Tag> registryOps;
    private final TagParser<Tag> tagParser;
 
    public ItemParser(HolderLookup.Provider registries) {
        this.items = registries.lookupOrThrow(Registries.ITEM);
        this.registryOps = registries.createSerializationContext(NbtOps.INSTANCE);
        this.tagParser = TagParser.create(this.registryOps);
    }
 
    public ItemInput parse(StringReader reader) throws CommandSyntaxException {
        final MutableObject<Holder<Item>> itemResult = new MutableObject<>();
        final DataComponentPatch.Builder componentsBuilder = DataComponentPatch.builder();
        this.parse(reader, new ItemParser.Visitor() {
            {
                Objects.requireNonNull(ItemParser.this);
            }
 
            @Override
            public void visitItem(Holder<Item> item) {
                itemResult.setValue(item);
            }
 
            @Override
            public <T> void visitComponent(DataComponentType<T> type, T value) {
                componentsBuilder.set(type, value);
            }
 
            @Override
            public <T> void visitRemovedComponent(DataComponentType<T> type) {
                componentsBuilder.remove(type);
            }
        });
        Holder<Item> item = Objects.requireNonNull(itemResult.get(), "Parser gave no item");
        DataComponentPatch components = componentsBuilder.build();
        return new ItemInput(item, components);
    }
 
    public void parse(StringReader reader, ItemParser.Visitor visitor) throws CommandSyntaxException {
        int cursor = reader.getCursor();
 
        try {
            new ItemParser.State(reader, visitor).parse();
        } catch (CommandSyntaxException var5) {
            reader.setCursor(cursor);
            throw var5;
        }
    }
 
    public CompletableFuture<Suggestions> fillSuggestions(SuggestionsBuilder builder) {
        StringReader reader = new StringReader(builder.getInput());
        reader.setCursor(builder.getStart());
        ItemParser.SuggestionsVisitor handler = new ItemParser.SuggestionsVisitor();
        ItemParser.State state = new ItemParser.State(reader, handler);
 
        try {
            state.parse();
        } catch (CommandSyntaxException var6) {
        }
 
        return handler.resolveSuggestions(builder, reader);
    }
 
    private class State {
        private final StringReader reader;
        private final ItemParser.Visitor visitor;
 
        private State(StringReader reader, ItemParser.Visitor visitor) {
            Objects.requireNonNull(ItemParser.this);
            super();
            this.reader = reader;
            this.visitor = visitor;
        }
 
        public void parse() throws CommandSyntaxException {
            this.visitor.visitSuggestions(this::suggestItem);
            this.readItem();
            this.visitor.visitSuggestions(this::suggestStartComponents);
            if (this.reader.canRead() && this.reader.peek() == '[') {
                this.visitor.visitSuggestions(ItemParser.SUGGEST_NOTHING);
                this.readComponents();
            }
        }
 
        private void readItem() throws CommandSyntaxException {
            int cursor = this.reader.getCursor();
            Identifier id = Identifier.read(this.reader);
            this.visitor.visitItem(ItemParser.this.items.get(ResourceKey.create(Registries.ITEM, id)).orElseThrow(() -> {
                this.reader.setCursor(cursor);
                return ItemParser.ERROR_UNKNOWN_ITEM.createWithContext(this.reader, id);
            }));
        }
 
        private void readComponents() throws CommandSyntaxException {
            this.reader.expect('[');
            this.visitor.visitSuggestions(this::suggestComponentAssignmentOrRemoval);
            Set<DataComponentType<?>> visitedComponents = new ReferenceArraySet<>();
 
            while (this.reader.canRead() && this.reader.peek() != ']') {
                this.reader.skipWhitespace();
                if (this.reader.canRead() && this.reader.peek() == '!') {
                    this.reader.skip();
                    this.visitor.visitSuggestions(this::suggestComponent);
                    DataComponentType<?> componentType = readComponentType(this.reader);
                    if (!visitedComponents.add(componentType)) {
                        throw ItemParser.ERROR_REPEATED_COMPONENT.create(componentType);
                    }
 
                    this.visitor.visitRemovedComponent(componentType);
                    this.visitor.visitSuggestions(ItemParser.SUGGEST_NOTHING);
                    this.reader.skipWhitespace();
                } else {
                    DataComponentType<?> componentType = readComponentType(this.reader);
                    if (!visitedComponents.add(componentType)) {
                        throw ItemParser.ERROR_REPEATED_COMPONENT.create(componentType);
                    }
 
                    this.visitor.visitSuggestions(this::suggestAssignment);
                    this.reader.skipWhitespace();
                    this.reader.expect('=');
                    this.visitor.visitSuggestions(ItemParser.SUGGEST_NOTHING);
                    this.reader.skipWhitespace();
                    this.readComponent(ItemParser.this.tagParser, ItemParser.this.registryOps, componentType);
                    this.reader.skipWhitespace();
                }
 
                this.visitor.visitSuggestions(this::suggestNextOrEndComponents);
                if (!this.reader.canRead() || this.reader.peek() != ',') {
                    break;
                }
 
                this.reader.skip();
                this.reader.skipWhitespace();
                this.visitor.visitSuggestions(this::suggestComponentAssignmentOrRemoval);
                if (!this.reader.canRead()) {
                    throw ItemParser.ERROR_EXPECTED_COMPONENT.createWithContext(this.reader);
                }
            }
 
            this.reader.expect(']');
            this.visitor.visitSuggestions(ItemParser.SUGGEST_NOTHING);
        }
 
        public static DataComponentType<?> readComponentType(StringReader reader) throws CommandSyntaxException {
            if (!reader.canRead()) {
                throw ItemParser.ERROR_EXPECTED_COMPONENT.createWithContext(reader);
            } else {
                int cursor = reader.getCursor();
                Identifier id = Identifier.read(reader);
                DataComponentType<?> component = BuiltInRegistries.DATA_COMPONENT_TYPE.getValue(id);
                if (component != null && !component.isTransient()) {
                    return component;
                } else {
                    reader.setCursor(cursor);
                    throw ItemParser.ERROR_UNKNOWN_COMPONENT.createWithContext(reader, id);
                }
            }
        }
 
        private <T, O> void readComponent(TagParser<O> tagParser, RegistryOps<O> registryOps, DataComponentType<T> componentType) throws CommandSyntaxException {
            int cursor = this.reader.getCursor();
            O tag = tagParser.parseAsArgument(this.reader);
            DataResult<T> result = componentType.codecOrThrow().parse(registryOps, tag);
            this.visitor.visitComponent(componentType, result.getOrThrow(message -> {
                this.reader.setCursor(cursor);
                return ItemParser.ERROR_MALFORMED_COMPONENT.createWithContext(this.reader, componentType.toString(), message);
            }));
        }
 
        private CompletableFuture<Suggestions> suggestStartComponents(SuggestionsBuilder builder) {
            if (builder.getRemaining().isEmpty()) {
                builder.suggest(String.valueOf('['));
            }
 
            return builder.buildFuture();
        }
 
        private CompletableFuture<Suggestions> suggestNextOrEndComponents(SuggestionsBuilder builder) {
            if (builder.getRemaining().isEmpty()) {
                builder.suggest(String.valueOf(','));
                builder.suggest(String.valueOf(']'));
            }
 
            return builder.buildFuture();
        }
 
        private CompletableFuture<Suggestions> suggestAssignment(SuggestionsBuilder builder) {
            if (builder.getRemaining().isEmpty()) {
                builder.suggest(String.valueOf('='));
            }
 
            return builder.buildFuture();
        }
 
        private CompletableFuture<Suggestions> suggestItem(SuggestionsBuilder builder) {
            return SharedSuggestionProvider.suggestResource(ItemParser.this.items.listElementIds().map(ResourceKey::identifier), builder);
        }
 
        private CompletableFuture<Suggestions> suggestComponentAssignmentOrRemoval(SuggestionsBuilder builder) {
            builder.suggest(String.valueOf('!'));
            return this.suggestComponent(builder, String.valueOf('='));
        }
 
        private CompletableFuture<Suggestions> suggestComponent(SuggestionsBuilder builder) {
            return this.suggestComponent(builder, "");
        }
 
        private CompletableFuture<Suggestions> suggestComponent(SuggestionsBuilder builder, String suffix) {
            String contents = builder.getRemaining().toLowerCase(Locale.ROOT);
            SharedSuggestionProvider.filterResources(
                BuiltInRegistries.DATA_COMPONENT_TYPE.entrySet(), contents, entry -> entry.getKey().identifier(), entry -> {
                    DataComponentType<?> type = entry.getValue();
                    if (type.codec() != null) {
                        Identifier id = entry.getKey().identifier();
                        builder.suggest(id + suffix);
                    }
                }
            );
            return builder.buildFuture();
        }
    }
 
    private static class SuggestionsVisitor implements ItemParser.Visitor {
        private Function<SuggestionsBuilder, CompletableFuture<Suggestions>> suggestions = ItemParser.SUGGEST_NOTHING;
 
        @Override
        public void visitSuggestions(Function<SuggestionsBuilder, CompletableFuture<Suggestions>> suggestions) {
            this.suggestions = suggestions;
        }
 
        public CompletableFuture<Suggestions> resolveSuggestions(SuggestionsBuilder builder, StringReader reader) {
            return this.suggestions.apply(builder.createOffset(reader.getCursor()));
        }
    }
 
    public interface Visitor {
        default void visitItem(Holder<Item> item) {
        }
 
        default <T> void visitComponent(DataComponentType<T> type, T value) {
        }
 
        default <T> void visitRemovedComponent(DataComponentType<T> type) {
        }
 
        default void visitSuggestions(Function<SuggestionsBuilder, CompletableFuture<Suggestions>> suggestions) {
        }
    }
}

引用的其他类

  • SharedSuggestionProvider

    • 引用位置: 方法调用
    • 关联成员: SharedSuggestionProvider.filterResources(), SharedSuggestionProvider.suggestResource()
  • ItemInput

    • 引用位置: 构造调用/返回值
    • 关联成员: ItemInput()
  • HolderLookup

    • 引用位置: 参数/字段
  • DataComponentPatch

    • 引用位置: 方法调用
    • 关联成员: DataComponentPatch.builder()
  • Tag

    • 引用位置: 字段
  • TagParser

    • 引用位置: 字段/方法调用
    • 关联成员: TagParser.create()
  • Component

    • 引用位置: 方法调用
    • 关联成员: Component.translatable(), Component.translatableEscape()
  • Identifier

    • 引用位置: 方法调用
    • 关联成员: Identifier.read()
  • RegistryOps

    • 引用位置: 字段
  • ResourceKey

    • 引用位置: 方法调用
    • 关联成员: ResourceKey.create()
  • Item

    • 引用位置: 字段