minecraft-src/net/minecraft/commands/arguments/item/ComponentPredicateParser.java
2025-07-04 03:45:38 +03:00

213 lines
8.6 KiB
Java

package net.minecraft.commands.arguments.item;
import com.google.common.collect.ImmutableList;
import com.google.common.collect.ImmutableList.Builder;
import com.mojang.brigadier.ImmutableStringReader;
import com.mojang.brigadier.StringReader;
import com.mojang.brigadier.exceptions.CommandSyntaxException;
import com.mojang.serialization.Dynamic;
import java.util.List;
import java.util.Optional;
import java.util.stream.Stream;
import net.minecraft.Util;
import net.minecraft.nbt.NbtOps;
import net.minecraft.resources.ResourceLocation;
import net.minecraft.util.Unit;
import net.minecraft.util.parsing.packrat.Atom;
import net.minecraft.util.parsing.packrat.Dictionary;
import net.minecraft.util.parsing.packrat.NamedRule;
import net.minecraft.util.parsing.packrat.Scope;
import net.minecraft.util.parsing.packrat.Term;
import net.minecraft.util.parsing.packrat.commands.Grammar;
import net.minecraft.util.parsing.packrat.commands.ResourceLocationParseRule;
import net.minecraft.util.parsing.packrat.commands.ResourceLookupRule;
import net.minecraft.util.parsing.packrat.commands.StringReaderTerms;
import net.minecraft.util.parsing.packrat.commands.TagParseRule;
public class ComponentPredicateParser {
public static <T, C, P> Grammar<List<T>> createGrammar(ComponentPredicateParser.Context<T, C, P> context) {
Atom<List<T>> atom = Atom.of("top");
Atom<Optional<T>> atom2 = Atom.of("type");
Atom<Unit> atom3 = Atom.of("any_type");
Atom<T> atom4 = Atom.of("element_type");
Atom<T> atom5 = Atom.of("tag_type");
Atom<List<T>> atom6 = Atom.of("conditions");
Atom<List<T>> atom7 = Atom.of("alternatives");
Atom<T> atom8 = Atom.of("term");
Atom<T> atom9 = Atom.of("negation");
Atom<T> atom10 = Atom.of("test");
Atom<C> atom11 = Atom.of("component_type");
Atom<P> atom12 = Atom.of("predicate_type");
Atom<ResourceLocation> atom13 = Atom.of("id");
Atom<Dynamic<?>> atom14 = Atom.of("tag");
Dictionary<StringReader> dictionary = new Dictionary<>();
NamedRule<StringReader, ResourceLocation> namedRule = dictionary.put(atom13, ResourceLocationParseRule.INSTANCE);
NamedRule<StringReader, List<T>> namedRule2 = dictionary.put(
atom,
Term.alternative(
Term.sequence(
dictionary.named(atom2), StringReaderTerms.character('['), Term.cut(), Term.optional(dictionary.named(atom6)), StringReaderTerms.character(']')
),
dictionary.named(atom2)
),
scope -> {
Builder<T> builder = ImmutableList.builder();
scope.getOrThrow(atom2).ifPresent(builder::add);
List<T> list = scope.get(atom6);
if (list != null) {
builder.addAll(list);
}
return builder.build();
}
);
dictionary.put(
atom2,
Term.alternative(dictionary.named(atom4), Term.sequence(StringReaderTerms.character('#'), Term.cut(), dictionary.named(atom5)), dictionary.named(atom3)),
scope -> Optional.ofNullable(scope.getAny(atom4, atom5))
);
dictionary.put(atom3, StringReaderTerms.character('*'), scope -> Unit.INSTANCE);
dictionary.put(atom4, new ComponentPredicateParser.ElementLookupRule<>(namedRule, context));
dictionary.put(atom5, new ComponentPredicateParser.TagLookupRule<>(namedRule, context));
dictionary.put(
atom6, Term.sequence(dictionary.named(atom7), Term.optional(Term.sequence(StringReaderTerms.character(','), dictionary.named(atom6)))), scope -> {
T object = context.anyOf(scope.getOrThrow(atom7));
return (List<T>)Optional.ofNullable(scope.get(atom6)).map(list -> Util.copyAndAdd(object, list)).orElse(List.of(object));
}
);
dictionary.put(
atom7, Term.sequence(dictionary.named(atom8), Term.optional(Term.sequence(StringReaderTerms.character('|'), dictionary.named(atom7)))), scope -> {
T object = scope.getOrThrow(atom8);
return (List<T>)Optional.ofNullable(scope.get(atom7)).map(list -> Util.copyAndAdd(object, list)).orElse(List.of(object));
}
);
dictionary.put(
atom8,
Term.alternative(dictionary.named(atom10), Term.sequence(StringReaderTerms.character('!'), dictionary.named(atom9))),
scope -> scope.getAnyOrThrow(atom10, atom9)
);
dictionary.put(atom9, dictionary.named(atom10), scope -> context.negate(scope.getOrThrow(atom10)));
dictionary.putComplex(
atom10,
Term.alternative(
Term.sequence(dictionary.named(atom11), StringReaderTerms.character('='), Term.cut(), dictionary.named(atom14)),
Term.sequence(dictionary.named(atom12), StringReaderTerms.character('~'), Term.cut(), dictionary.named(atom14)),
dictionary.named(atom11)
),
parseState -> {
Scope scope = parseState.scope();
P object = scope.get(atom12);
try {
if (object != null) {
Dynamic<?> dynamic = scope.getOrThrow(atom14);
return context.createPredicateTest(parseState.input(), object, dynamic);
} else {
C object2 = scope.getOrThrow(atom11);
Dynamic<?> dynamic2 = scope.get(atom14);
return dynamic2 != null ? context.createComponentTest(parseState.input(), object2, dynamic2) : context.createComponentTest(parseState.input(), object2);
}
} catch (CommandSyntaxException var9x) {
parseState.errorCollector().store(parseState.mark(), var9x);
return null;
}
}
);
dictionary.put(atom11, new ComponentPredicateParser.ComponentLookupRule<>(namedRule, context));
dictionary.put(atom12, new ComponentPredicateParser.PredicateLookupRule<>(namedRule, context));
dictionary.put(atom14, new TagParseRule<>(NbtOps.INSTANCE));
return new Grammar<>(dictionary, namedRule2);
}
static class ComponentLookupRule<T, C, P> extends ResourceLookupRule<ComponentPredicateParser.Context<T, C, P>, C> {
ComponentLookupRule(NamedRule<StringReader, ResourceLocation> idParser, ComponentPredicateParser.Context<T, C, P> context) {
super(idParser, context);
}
@Override
protected C validateElement(ImmutableStringReader reader, ResourceLocation elementType) throws Exception {
return this.context.lookupComponentType(reader, elementType);
}
@Override
public Stream<ResourceLocation> possibleResources() {
return this.context.listComponentTypes();
}
}
public interface Context<T, C, P> {
T forElementType(ImmutableStringReader reader, ResourceLocation elementType) throws CommandSyntaxException;
Stream<ResourceLocation> listElementTypes();
T forTagType(ImmutableStringReader reader, ResourceLocation tagType) throws CommandSyntaxException;
Stream<ResourceLocation> listTagTypes();
C lookupComponentType(ImmutableStringReader reader, ResourceLocation componentType) throws CommandSyntaxException;
Stream<ResourceLocation> listComponentTypes();
T createComponentTest(ImmutableStringReader reader, C context, Dynamic<?> data) throws CommandSyntaxException;
T createComponentTest(ImmutableStringReader reader, C context);
P lookupPredicateType(ImmutableStringReader reader, ResourceLocation predicateType) throws CommandSyntaxException;
Stream<ResourceLocation> listPredicateTypes();
T createPredicateTest(ImmutableStringReader reader, P predicateType, Dynamic<?> data) throws CommandSyntaxException;
T negate(T value);
T anyOf(List<T> values);
}
static class ElementLookupRule<T, C, P> extends ResourceLookupRule<ComponentPredicateParser.Context<T, C, P>, T> {
ElementLookupRule(NamedRule<StringReader, ResourceLocation> idParser, ComponentPredicateParser.Context<T, C, P> context) {
super(idParser, context);
}
@Override
protected T validateElement(ImmutableStringReader reader, ResourceLocation elementType) throws Exception {
return this.context.forElementType(reader, elementType);
}
@Override
public Stream<ResourceLocation> possibleResources() {
return this.context.listElementTypes();
}
}
static class PredicateLookupRule<T, C, P> extends ResourceLookupRule<ComponentPredicateParser.Context<T, C, P>, P> {
PredicateLookupRule(NamedRule<StringReader, ResourceLocation> idParser, ComponentPredicateParser.Context<T, C, P> context) {
super(idParser, context);
}
@Override
protected P validateElement(ImmutableStringReader reader, ResourceLocation elementType) throws Exception {
return this.context.lookupPredicateType(reader, elementType);
}
@Override
public Stream<ResourceLocation> possibleResources() {
return this.context.listPredicateTypes();
}
}
static class TagLookupRule<T, C, P> extends ResourceLookupRule<ComponentPredicateParser.Context<T, C, P>, T> {
TagLookupRule(NamedRule<StringReader, ResourceLocation> idParser, ComponentPredicateParser.Context<T, C, P> context) {
super(idParser, context);
}
@Override
protected T validateElement(ImmutableStringReader reader, ResourceLocation elementType) throws Exception {
return this.context.forTagType(reader, elementType);
}
@Override
public Stream<ResourceLocation> possibleResources() {
return this.context.listTagTypes();
}
}
}