213 lines
8.6 KiB
Java
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();
|
|
}
|
|
}
|
|
}
|