BlockStateParser.java

net.minecraft.commands.arguments.blocks.BlockStateParser

信息

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

    TODO

字段/常量

  • ERROR_NO_TAGS_ALLOWED

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

      TODO

  • ERROR_UNKNOWN_BLOCK

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

      TODO

  • ERROR_UNKNOWN_PROPERTY

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

      TODO

  • ERROR_DUPLICATE_PROPERTY

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

      TODO

  • ERROR_INVALID_VALUE

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

      TODO

  • ERROR_EXPECTED_VALUE

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

      TODO

  • ERROR_EXPECTED_END_OF_PROPERTIES

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

      TODO

  • ERROR_UNKNOWN_TAG

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

      TODO

  • SYNTAX_START_PROPERTIES

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

      TODO

  • SYNTAX_START_NBT

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

      TODO

  • SYNTAX_END_PROPERTIES

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

      TODO

  • SYNTAX_EQUALS

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

      TODO

  • SYNTAX_PROPERTY_SEPARATOR

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

      TODO

  • SYNTAX_TAG

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

      TODO

  • SUGGEST_NOTHING

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

      TODO

  • blocks

    • 类型: HolderLookup<Block>
    • 修饰符: private final
    • 源码定位: L68
    • 说明:

      TODO

  • reader

    • 类型: StringReader
    • 修饰符: private final
    • 源码定位: L69
    • 说明:

      TODO

  • forTesting

    • 类型: boolean
    • 修饰符: private final
    • 源码定位: L70
    • 说明:

      TODO

  • allowNbt

    • 类型: boolean
    • 修饰符: private final
    • 源码定位: L71
    • 说明:

      TODO

  • properties

    • 类型: Map<Property<?>,Comparable<?>>
    • 修饰符: private final
    • 源码定位: L72
    • 说明:

      TODO

  • vagueProperties

    • 类型: Map<String,String>
    • 修饰符: private final
    • 源码定位: L73
    • 说明:

      TODO

  • id

    • 类型: Identifier
    • 修饰符: private
    • 源码定位: L74
    • 说明:

      TODO

  • definition

    • 类型: StateDefinition<Block,BlockState>
    • 修饰符: private
    • 源码定位: L75
    • 说明:

      TODO

  • state

    • 类型: BlockState
    • 修饰符: private
    • 源码定位: L76
    • 说明:

      TODO

  • nbt

    • 类型: CompoundTag
    • 修饰符: private
    • 源码定位: L77
    • 说明:

      TODO

  • tag

    • 类型: HolderSet<Block>
    • 修饰符: private
    • 源码定位: L78
    • 说明:

      TODO

  • suggestions

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

      TODO

内部类/嵌套类型

  • net.minecraft.commands.arguments.blocks.BlockStateParser.BlockResult

    • 类型: record
    • 修饰符: public
    • 源码定位: L521
    • 说明:

      TODO

  • net.minecraft.commands.arguments.blocks.BlockStateParser.TagResult

    • 类型: record
    • 修饰符: public
    • 源码定位: L524
    • 说明:

      TODO

构造器

private BlockStateParser(HolderLookup<Block> blocks, StringReader reader, boolean forTesting, boolean allowNbt) @ L81

  • 构造器名:BlockStateParser
  • 源码定位:L81
  • 修饰符:private

参数:

  • blocks: HolderLookup
  • reader: StringReader
  • forTesting: boolean
  • allowNbt: boolean

说明:

TODO

方法

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

public static BlockStateParser.BlockResult parseForBlock(HolderLookup<Block> blocks, String value, boolean allowNbt) @ L88

  • 方法名:parseForBlock
  • 源码定位:L88
  • 返回类型:BlockStateParser.BlockResult
  • 修饰符:public static

参数:

  • blocks: HolderLookup
  • value: String
  • allowNbt: boolean

说明:

TODO

public static BlockStateParser.BlockResult parseForBlock(HolderLookup<Block> blocks, StringReader reader, boolean allowNbt) @ L92

  • 方法名:parseForBlock
  • 源码定位:L92
  • 返回类型:BlockStateParser.BlockResult
  • 修饰符:public static

参数:

  • blocks: HolderLookup
  • reader: StringReader
  • allowNbt: boolean

说明:

TODO

public static Either<BlockStateParser.BlockResult,BlockStateParser.TagResult> parseForTesting(HolderLookup<Block> blocks, String value, boolean allowNbt) @ L105

  • 方法名:parseForTesting
  • 源码定位:L105
  • 返回类型:Either<BlockStateParser.BlockResult,BlockStateParser.TagResult>
  • 修饰符:public static

参数:

  • blocks: HolderLookup
  • value: String
  • allowNbt: boolean

说明:

TODO

public static Either<BlockStateParser.BlockResult,BlockStateParser.TagResult> parseForTesting(HolderLookup<Block> blocks, StringReader reader, boolean allowNbt) @ L109

  • 方法名:parseForTesting
  • 源码定位:L109
  • 返回类型:Either<BlockStateParser.BlockResult,BlockStateParser.TagResult>
  • 修饰符:public static

参数:

  • blocks: HolderLookup
  • reader: StringReader
  • allowNbt: boolean

说明:

TODO

public static CompletableFuture<Suggestions> fillSuggestions(HolderLookup<Block> blocks, SuggestionsBuilder builder, boolean forTesting, boolean allowNbt) @ L126

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

参数:

  • blocks: HolderLookup
  • builder: SuggestionsBuilder
  • forTesting: boolean
  • allowNbt: boolean

说明:

TODO

private void parse() @ L139

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

参数:

说明:

TODO

private CompletableFuture<Suggestions> suggestPropertyNameOrEnd(SuggestionsBuilder builder) @ L168

  • 方法名:suggestPropertyNameOrEnd
  • 源码定位:L168
  • 返回类型:CompletableFuture
  • 修饰符:private

参数:

  • builder: SuggestionsBuilder

说明:

TODO

private CompletableFuture<Suggestions> suggestVaguePropertyNameOrEnd(SuggestionsBuilder builder) @ L176

  • 方法名:suggestVaguePropertyNameOrEnd
  • 源码定位:L176
  • 返回类型:CompletableFuture
  • 修饰符:private

参数:

  • builder: SuggestionsBuilder

说明:

TODO

private CompletableFuture<Suggestions> suggestPropertyName(SuggestionsBuilder builder) @ L184

  • 方法名:suggestPropertyName
  • 源码定位:L184
  • 返回类型:CompletableFuture
  • 修饰符:private

参数:

  • builder: SuggestionsBuilder

说明:

TODO

private CompletableFuture<Suggestions> suggestVaguePropertyName(SuggestionsBuilder builder) @ L196

  • 方法名:suggestVaguePropertyName
  • 源码定位:L196
  • 返回类型:CompletableFuture
  • 修饰符:private

参数:

  • builder: SuggestionsBuilder

说明:

TODO

private CompletableFuture<Suggestions> suggestOpenNbt(SuggestionsBuilder builder) @ L211

  • 方法名:suggestOpenNbt
  • 源码定位:L211
  • 返回类型:CompletableFuture
  • 修饰符:private

参数:

  • builder: SuggestionsBuilder

说明:

TODO

private boolean hasBlockEntity() @ L219

  • 方法名:hasBlockEntity
  • 源码定位:L219
  • 返回类型:boolean
  • 修饰符:private

参数:

说明:

TODO

private CompletableFuture<Suggestions> suggestEquals(SuggestionsBuilder builder) @ L235

  • 方法名:suggestEquals
  • 源码定位:L235
  • 返回类型:CompletableFuture
  • 修饰符:private

参数:

  • builder: SuggestionsBuilder

说明:

TODO

private CompletableFuture<Suggestions> suggestNextPropertyOrEnd(SuggestionsBuilder builder) @ L243

  • 方法名:suggestNextPropertyOrEnd
  • 源码定位:L243
  • 返回类型:CompletableFuture
  • 修饰符:private

参数:

  • builder: SuggestionsBuilder

说明:

TODO

private static <T extends Comparable<T>> SuggestionsBuilder addSuggestions(SuggestionsBuilder builder, Property<T> property) @ L255

  • 方法名:addSuggestions
  • 源码定位:L255
  • 返回类型:<T extends Comparable> SuggestionsBuilder
  • 修饰符:private static

参数:

  • builder: SuggestionsBuilder
  • property: Property

说明:

TODO

private CompletableFuture<Suggestions> suggestVaguePropertyValue(SuggestionsBuilder builder, String key) @ L267

  • 方法名:suggestVaguePropertyValue
  • 源码定位:L267
  • 返回类型:CompletableFuture
  • 修饰符:private

参数:

  • builder: SuggestionsBuilder
  • key: String

说明:

TODO

private CompletableFuture<Suggestions> suggestOpenVaguePropertiesOrNbt(SuggestionsBuilder builder) @ L296

  • 方法名:suggestOpenVaguePropertiesOrNbt
  • 源码定位:L296
  • 返回类型:CompletableFuture
  • 修饰符:private

参数:

  • builder: SuggestionsBuilder

说明:

TODO

private CompletableFuture<Suggestions> suggestOpenPropertiesOrNbt(SuggestionsBuilder builder) @ L322

  • 方法名:suggestOpenPropertiesOrNbt
  • 源码定位:L322
  • 返回类型:CompletableFuture
  • 修饰符:private

参数:

  • builder: SuggestionsBuilder

说明:

TODO

private CompletableFuture<Suggestions> suggestTag(SuggestionsBuilder builder) @ L336

  • 方法名:suggestTag
  • 源码定位:L336
  • 返回类型:CompletableFuture
  • 修饰符:private

参数:

  • builder: SuggestionsBuilder

说明:

TODO

private CompletableFuture<Suggestions> suggestItem(SuggestionsBuilder builder) @ L340

  • 方法名:suggestItem
  • 源码定位:L340
  • 返回类型:CompletableFuture
  • 修饰符:private

参数:

  • builder: SuggestionsBuilder

说明:

TODO

private CompletableFuture<Suggestions> suggestBlockIdOrTag(SuggestionsBuilder builder) @ L344

  • 方法名:suggestBlockIdOrTag
  • 源码定位:L344
  • 返回类型:CompletableFuture
  • 修饰符:private

参数:

  • builder: SuggestionsBuilder

说明:

TODO

private void readBlock() @ L350

  • 方法名:readBlock
  • 源码定位:L350
  • 返回类型:void
  • 修饰符:private

参数:

说明:

TODO

private void readTag() @ L361

  • 方法名:readTag
  • 源码定位:L361
  • 返回类型:void
  • 修饰符:private

参数:

说明:

TODO

private void readProperties() @ L376

  • 方法名:readProperties
  • 源码定位:L376
  • 返回类型:void
  • 修饰符:private

参数:

说明:

TODO

private void readVagueProperties() @ L429

  • 方法名:readVagueProperties
  • 源码定位:L429
  • 返回类型:void
  • 修饰符:private

参数:

说明:

TODO

private void readNbt() @ L482

  • 方法名:readNbt
  • 源码定位:L482
  • 返回类型:void
  • 修饰符:private

参数:

说明:

TODO

private <T extends Comparable<T>> void setValue(Property<T> property, String raw, int start) @ L486

  • 方法名:setValue
  • 源码定位:L486
  • 返回类型:<T extends Comparable> void
  • 修饰符:private

参数:

  • property: Property
  • raw: String
  • start: int

说明:

TODO

public static String serialize(BlockState state) @ L497

  • 方法名:serialize
  • 源码定位:L497
  • 返回类型:String
  • 修饰符:public static

参数:

  • state: BlockState

说明:

TODO

代码

public class BlockStateParser {
    public static final SimpleCommandExceptionType ERROR_NO_TAGS_ALLOWED = new SimpleCommandExceptionType(
        Component.translatable("argument.block.tag.disallowed")
    );
    public static final DynamicCommandExceptionType ERROR_UNKNOWN_BLOCK = new DynamicCommandExceptionType(
        id -> Component.translatableEscape("argument.block.id.invalid", id)
    );
    public static final Dynamic2CommandExceptionType ERROR_UNKNOWN_PROPERTY = new Dynamic2CommandExceptionType(
        (block, property) -> Component.translatableEscape("argument.block.property.unknown", block, property)
    );
    public static final Dynamic2CommandExceptionType ERROR_DUPLICATE_PROPERTY = new Dynamic2CommandExceptionType(
        (block, property) -> Component.translatableEscape("argument.block.property.duplicate", property, block)
    );
    public static final Dynamic3CommandExceptionType ERROR_INVALID_VALUE = new Dynamic3CommandExceptionType(
        (block, property, value) -> Component.translatableEscape("argument.block.property.invalid", block, value, property)
    );
    public static final Dynamic2CommandExceptionType ERROR_EXPECTED_VALUE = new Dynamic2CommandExceptionType(
        (block, property) -> Component.translatableEscape("argument.block.property.novalue", property, block)
    );
    public static final SimpleCommandExceptionType ERROR_EXPECTED_END_OF_PROPERTIES = new SimpleCommandExceptionType(
        Component.translatable("argument.block.property.unclosed")
    );
    public static final DynamicCommandExceptionType ERROR_UNKNOWN_TAG = new DynamicCommandExceptionType(
        tag -> Component.translatableEscape("arguments.block.tag.unknown", tag)
    );
    private static final char SYNTAX_START_PROPERTIES = '[';
    private static final char SYNTAX_START_NBT = '{';
    private static final char SYNTAX_END_PROPERTIES = ']';
    private static final char SYNTAX_EQUALS = '=';
    private static final char SYNTAX_PROPERTY_SEPARATOR = ',';
    private static final char SYNTAX_TAG = '#';
    private static final Function<SuggestionsBuilder, CompletableFuture<Suggestions>> SUGGEST_NOTHING = SuggestionsBuilder::buildFuture;
    private final HolderLookup<Block> blocks;
    private final StringReader reader;
    private final boolean forTesting;
    private final boolean allowNbt;
    private final Map<Property<?>, Comparable<?>> properties = Maps.newHashMap();
    private final Map<String, String> vagueProperties = Maps.newHashMap();
    private Identifier id = Identifier.withDefaultNamespace("");
    private @Nullable StateDefinition<Block, BlockState> definition;
    private @Nullable BlockState state;
    private @Nullable CompoundTag nbt;
    private @Nullable HolderSet<Block> tag;
    private Function<SuggestionsBuilder, CompletableFuture<Suggestions>> suggestions = SUGGEST_NOTHING;
 
    private BlockStateParser(HolderLookup<Block> blocks, StringReader reader, boolean forTesting, boolean allowNbt) {
        this.blocks = blocks;
        this.reader = reader;
        this.forTesting = forTesting;
        this.allowNbt = allowNbt;
    }
 
    public static BlockStateParser.BlockResult parseForBlock(HolderLookup<Block> blocks, String value, boolean allowNbt) throws CommandSyntaxException {
        return parseForBlock(blocks, new StringReader(value), allowNbt);
    }
 
    public static BlockStateParser.BlockResult parseForBlock(HolderLookup<Block> blocks, StringReader reader, boolean allowNbt) throws CommandSyntaxException {
        int cursor = reader.getCursor();
 
        try {
            BlockStateParser parser = new BlockStateParser(blocks, reader, false, allowNbt);
            parser.parse();
            return new BlockStateParser.BlockResult(parser.state, parser.properties, parser.nbt);
        } catch (CommandSyntaxException var5) {
            reader.setCursor(cursor);
            throw var5;
        }
    }
 
    public static Either<BlockStateParser.BlockResult, BlockStateParser.TagResult> parseForTesting(HolderLookup<Block> blocks, String value, boolean allowNbt) throws CommandSyntaxException {
        return parseForTesting(blocks, new StringReader(value), allowNbt);
    }
 
    public static Either<BlockStateParser.BlockResult, BlockStateParser.TagResult> parseForTesting(
        HolderLookup<Block> blocks, StringReader reader, boolean allowNbt
    ) throws CommandSyntaxException {
        int cursor = reader.getCursor();
 
        try {
            BlockStateParser parser = new BlockStateParser(blocks, reader, true, allowNbt);
            parser.parse();
            return parser.tag != null
                ? Either.right(new BlockStateParser.TagResult(parser.tag, parser.vagueProperties, parser.nbt))
                : Either.left(new BlockStateParser.BlockResult(parser.state, parser.properties, parser.nbt));
        } catch (CommandSyntaxException var5) {
            reader.setCursor(cursor);
            throw var5;
        }
    }
 
    public static CompletableFuture<Suggestions> fillSuggestions(HolderLookup<Block> blocks, SuggestionsBuilder builder, boolean forTesting, boolean allowNbt) {
        StringReader reader = new StringReader(builder.getInput());
        reader.setCursor(builder.getStart());
        BlockStateParser parser = new BlockStateParser(blocks, reader, forTesting, allowNbt);
 
        try {
            parser.parse();
        } catch (CommandSyntaxException var7) {
        }
 
        return parser.suggestions.apply(builder.createOffset(reader.getCursor()));
    }
 
    private void parse() throws CommandSyntaxException {
        if (this.forTesting) {
            this.suggestions = this::suggestBlockIdOrTag;
        } else {
            this.suggestions = this::suggestItem;
        }
 
        if (this.reader.canRead() && this.reader.peek() == '#') {
            this.readTag();
            this.suggestions = this::suggestOpenVaguePropertiesOrNbt;
            if (this.reader.canRead() && this.reader.peek() == '[') {
                this.readVagueProperties();
                this.suggestions = this::suggestOpenNbt;
            }
        } else {
            this.readBlock();
            this.suggestions = this::suggestOpenPropertiesOrNbt;
            if (this.reader.canRead() && this.reader.peek() == '[') {
                this.readProperties();
                this.suggestions = this::suggestOpenNbt;
            }
        }
 
        if (this.allowNbt && this.reader.canRead() && this.reader.peek() == '{') {
            this.suggestions = SUGGEST_NOTHING;
            this.readNbt();
        }
    }
 
    private CompletableFuture<Suggestions> suggestPropertyNameOrEnd(SuggestionsBuilder builder) {
        if (builder.getRemaining().isEmpty()) {
            builder.suggest(String.valueOf(']'));
        }
 
        return this.suggestPropertyName(builder);
    }
 
    private CompletableFuture<Suggestions> suggestVaguePropertyNameOrEnd(SuggestionsBuilder builder) {
        if (builder.getRemaining().isEmpty()) {
            builder.suggest(String.valueOf(']'));
        }
 
        return this.suggestVaguePropertyName(builder);
    }
 
    private CompletableFuture<Suggestions> suggestPropertyName(SuggestionsBuilder builder) {
        String prefix = builder.getRemaining().toLowerCase(Locale.ROOT);
 
        for (Property<?> property : this.state.getProperties()) {
            if (!this.properties.containsKey(property) && property.getName().startsWith(prefix)) {
                builder.suggest(property.getName() + "=");
            }
        }
 
        return builder.buildFuture();
    }
 
    private CompletableFuture<Suggestions> suggestVaguePropertyName(SuggestionsBuilder builder) {
        String prefix = builder.getRemaining().toLowerCase(Locale.ROOT);
        if (this.tag != null) {
            for (Holder<Block> block : this.tag) {
                for (Property<?> property : block.value().getStateDefinition().getProperties()) {
                    if (!this.vagueProperties.containsKey(property.getName()) && property.getName().startsWith(prefix)) {
                        builder.suggest(property.getName() + "=");
                    }
                }
            }
        }
 
        return builder.buildFuture();
    }
 
    private CompletableFuture<Suggestions> suggestOpenNbt(SuggestionsBuilder builder) {
        if (builder.getRemaining().isEmpty() && this.hasBlockEntity()) {
            builder.suggest(String.valueOf('{'));
        }
 
        return builder.buildFuture();
    }
 
    private boolean hasBlockEntity() {
        if (this.state != null) {
            return this.state.hasBlockEntity();
        } else {
            if (this.tag != null) {
                for (Holder<Block> block : this.tag) {
                    if (block.value().defaultBlockState().hasBlockEntity()) {
                        return true;
                    }
                }
            }
 
            return false;
        }
    }
 
    private CompletableFuture<Suggestions> suggestEquals(SuggestionsBuilder builder) {
        if (builder.getRemaining().isEmpty()) {
            builder.suggest(String.valueOf('='));
        }
 
        return builder.buildFuture();
    }
 
    private CompletableFuture<Suggestions> suggestNextPropertyOrEnd(SuggestionsBuilder builder) {
        if (builder.getRemaining().isEmpty()) {
            builder.suggest(String.valueOf(']'));
        }
 
        if (builder.getRemaining().isEmpty() && this.properties.size() < this.state.getProperties().size()) {
            builder.suggest(String.valueOf(','));
        }
 
        return builder.buildFuture();
    }
 
    private static <T extends Comparable<T>> SuggestionsBuilder addSuggestions(SuggestionsBuilder builder, Property<T> property) {
        for (T value : property.getPossibleValues()) {
            if (value instanceof Integer v) {
                builder.suggest(v);
            } else {
                builder.suggest(property.getName(value));
            }
        }
 
        return builder;
    }
 
    private CompletableFuture<Suggestions> suggestVaguePropertyValue(SuggestionsBuilder builder, String key) {
        boolean hasMoreProperties = false;
        if (this.tag != null) {
            for (Holder<Block> blockHolder : this.tag) {
                Block block = blockHolder.value();
                Property<?> property = block.getStateDefinition().getProperty(key);
                if (property != null) {
                    addSuggestions(builder, property);
                }
 
                if (!hasMoreProperties) {
                    for (Property<?> prop : block.getStateDefinition().getProperties()) {
                        if (!this.vagueProperties.containsKey(prop.getName())) {
                            hasMoreProperties = true;
                            break;
                        }
                    }
                }
            }
        }
 
        if (hasMoreProperties) {
            builder.suggest(String.valueOf(','));
        }
 
        builder.suggest(String.valueOf(']'));
        return builder.buildFuture();
    }
 
    private CompletableFuture<Suggestions> suggestOpenVaguePropertiesOrNbt(SuggestionsBuilder builder) {
        if (builder.getRemaining().isEmpty() && this.tag != null) {
            boolean hasProperties = false;
            boolean hasEntity = false;
 
            for (Holder<Block> blockHolder : this.tag) {
                Block block = blockHolder.value();
                hasProperties |= !block.getStateDefinition().getProperties().isEmpty();
                hasEntity |= block.defaultBlockState().hasBlockEntity();
                if (hasProperties && hasEntity) {
                    break;
                }
            }
 
            if (hasProperties) {
                builder.suggest(String.valueOf('['));
            }
 
            if (hasEntity) {
                builder.suggest(String.valueOf('{'));
            }
        }
 
        return builder.buildFuture();
    }
 
    private CompletableFuture<Suggestions> suggestOpenPropertiesOrNbt(SuggestionsBuilder builder) {
        if (builder.getRemaining().isEmpty()) {
            if (!this.definition.getProperties().isEmpty()) {
                builder.suggest(String.valueOf('['));
            }
 
            if (this.state.hasBlockEntity()) {
                builder.suggest(String.valueOf('{'));
            }
        }
 
        return builder.buildFuture();
    }
 
    private CompletableFuture<Suggestions> suggestTag(SuggestionsBuilder builder) {
        return SharedSuggestionProvider.suggestResource(this.blocks.listTagIds().map(TagKey::location), builder, String.valueOf('#'));
    }
 
    private CompletableFuture<Suggestions> suggestItem(SuggestionsBuilder builder) {
        return SharedSuggestionProvider.suggestResource(this.blocks.listElementIds().map(ResourceKey::identifier), builder);
    }
 
    private CompletableFuture<Suggestions> suggestBlockIdOrTag(SuggestionsBuilder builder) {
        this.suggestTag(builder);
        this.suggestItem(builder);
        return builder.buildFuture();
    }
 
    private void readBlock() throws CommandSyntaxException {
        int start = this.reader.getCursor();
        this.id = Identifier.read(this.reader);
        Block block = this.blocks.get(ResourceKey.create(Registries.BLOCK, this.id)).orElseThrow(() -> {
            this.reader.setCursor(start);
            return ERROR_UNKNOWN_BLOCK.createWithContext(this.reader, this.id.toString());
        }).value();
        this.definition = block.getStateDefinition();
        this.state = block.defaultBlockState();
    }
 
    private void readTag() throws CommandSyntaxException {
        if (!this.forTesting) {
            throw ERROR_NO_TAGS_ALLOWED.createWithContext(this.reader);
        } else {
            int start = this.reader.getCursor();
            this.reader.expect('#');
            this.suggestions = this::suggestTag;
            Identifier id = Identifier.read(this.reader);
            this.tag = this.blocks.get(TagKey.create(Registries.BLOCK, id)).orElseThrow(() -> {
                this.reader.setCursor(start);
                return ERROR_UNKNOWN_TAG.createWithContext(this.reader, id.toString());
            });
        }
    }
 
    private void readProperties() throws CommandSyntaxException {
        this.reader.skip();
        this.suggestions = this::suggestPropertyNameOrEnd;
        this.reader.skipWhitespace();
 
        while (this.reader.canRead() && this.reader.peek() != ']') {
            this.reader.skipWhitespace();
            int keyStart = this.reader.getCursor();
            String key = this.reader.readString();
            Property<?> property = this.definition.getProperty(key);
            if (property == null) {
                this.reader.setCursor(keyStart);
                throw ERROR_UNKNOWN_PROPERTY.createWithContext(this.reader, this.id.toString(), key);
            }
 
            if (this.properties.containsKey(property)) {
                this.reader.setCursor(keyStart);
                throw ERROR_DUPLICATE_PROPERTY.createWithContext(this.reader, this.id.toString(), key);
            }
 
            this.reader.skipWhitespace();
            this.suggestions = this::suggestEquals;
            if (!this.reader.canRead() || this.reader.peek() != '=') {
                throw ERROR_EXPECTED_VALUE.createWithContext(this.reader, this.id.toString(), key);
            }
 
            this.reader.skip();
            this.reader.skipWhitespace();
            this.suggestions = builder -> addSuggestions(builder, property).buildFuture();
            int start = this.reader.getCursor();
            this.setValue(property, this.reader.readString(), start);
            this.suggestions = this::suggestNextPropertyOrEnd;
            this.reader.skipWhitespace();
            if (this.reader.canRead()) {
                if (this.reader.peek() != ',') {
                    if (this.reader.peek() != ']') {
                        throw ERROR_EXPECTED_END_OF_PROPERTIES.createWithContext(this.reader);
                    }
                    break;
                }
 
                this.reader.skip();
                this.suggestions = this::suggestPropertyName;
            }
        }
 
        if (this.reader.canRead()) {
            this.reader.skip();
        } else {
            throw ERROR_EXPECTED_END_OF_PROPERTIES.createWithContext(this.reader);
        }
    }
 
    private void readVagueProperties() throws CommandSyntaxException {
        this.reader.skip();
        this.suggestions = this::suggestVaguePropertyNameOrEnd;
        int valueStart = -1;
        this.reader.skipWhitespace();
 
        while (this.reader.canRead() && this.reader.peek() != ']') {
            this.reader.skipWhitespace();
            int keyStart = this.reader.getCursor();
            String key = this.reader.readString();
            if (this.vagueProperties.containsKey(key)) {
                this.reader.setCursor(keyStart);
                throw ERROR_DUPLICATE_PROPERTY.createWithContext(this.reader, this.id.toString(), key);
            }
 
            this.reader.skipWhitespace();
            if (!this.reader.canRead() || this.reader.peek() != '=') {
                this.reader.setCursor(keyStart);
                throw ERROR_EXPECTED_VALUE.createWithContext(this.reader, this.id.toString(), key);
            }
 
            this.reader.skip();
            this.reader.skipWhitespace();
            this.suggestions = builder -> this.suggestVaguePropertyValue(builder, key);
            valueStart = this.reader.getCursor();
            String value = this.reader.readString();
            this.vagueProperties.put(key, value);
            this.reader.skipWhitespace();
            if (this.reader.canRead()) {
                valueStart = -1;
                if (this.reader.peek() != ',') {
                    if (this.reader.peek() != ']') {
                        throw ERROR_EXPECTED_END_OF_PROPERTIES.createWithContext(this.reader);
                    }
                    break;
                }
 
                this.reader.skip();
                this.suggestions = this::suggestVaguePropertyName;
            }
        }
 
        if (this.reader.canRead()) {
            this.reader.skip();
        } else {
            if (valueStart >= 0) {
                this.reader.setCursor(valueStart);
            }
 
            throw ERROR_EXPECTED_END_OF_PROPERTIES.createWithContext(this.reader);
        }
    }
 
    private void readNbt() throws CommandSyntaxException {
        this.nbt = TagParser.parseCompoundAsArgument(this.reader);
    }
 
    private <T extends Comparable<T>> void setValue(Property<T> property, String raw, int start) throws CommandSyntaxException {
        Optional<T> value = property.getValue(raw);
        if (value.isPresent()) {
            this.state = this.state.setValue(property, value.get());
            this.properties.put(property, value.get());
        } else {
            this.reader.setCursor(start);
            throw ERROR_INVALID_VALUE.createWithContext(this.reader, this.id.toString(), property.getName(), raw);
        }
    }
 
    public static String serialize(BlockState state) {
        final StringBuilder result = new StringBuilder(state.typeHolder().unwrapKey().map(r -> r.identifier().toString()).orElse("air"));
        if (!state.isSingletonState()) {
            result.append('[');
            state.getValues().forEach(new Consumer<Property.Value<?>>() {
                private boolean separate = false;
 
                public void accept(Property.Value<?> value) {
                    if (this.separate) {
                        result.append(',');
                    }
 
                    result.append(value.property().getName());
                    result.append('=');
                    result.append(value.valueName());
                    this.separate = true;
                }
            });
            result.append(']');
        }
 
        return result.toString();
    }
 
    public record BlockResult(BlockState blockState, Map<Property<?>, Comparable<?>> properties, @Nullable CompoundTag nbt) {
    }
 
    public record TagResult(HolderSet<Block> tag, Map<String, String> vagueProperties, @Nullable CompoundTag nbt) {
    }
}

引用的其他类

  • SharedSuggestionProvider

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

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

    • 引用位置: 字段
  • CompoundTag

    • 引用位置: 字段
  • TagParser

    • 引用位置: 方法调用
    • 关联成员: TagParser.parseCompoundAsArgument()
  • Component

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

    • 引用位置: 字段/方法调用
    • 关联成员: Identifier.read(), Identifier.withDefaultNamespace()
  • ResourceKey

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

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

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

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

    • 引用位置: 字段
  • Property

    • 引用位置: 参数/字段