package net.minecraft.core.component; import com.google.common.collect.ImmutableList; import com.mojang.serialization.Codec; import java.util.ArrayList; import java.util.List; import java.util.Map; import java.util.Objects; import java.util.function.Predicate; import java.util.stream.Collectors; import net.minecraft.network.RegistryFriendlyByteBuf; import net.minecraft.network.codec.ByteBufCodecs; import net.minecraft.network.codec.StreamCodec; public final class DataComponentExactPredicate implements Predicate { public static final Codec CODEC = DataComponentType.VALUE_MAP_CODEC .xmap( map -> new DataComponentExactPredicate( (List>)map.entrySet().stream().map(TypedDataComponent::fromEntryUnchecked).collect(Collectors.toList()) ), dataComponentExactPredicate -> (Map)dataComponentExactPredicate.expectedComponents .stream() .filter(typedDataComponent -> !typedDataComponent.type().isTransient()) .collect(Collectors.toMap(TypedDataComponent::type, TypedDataComponent::value)) ); public static final StreamCodec STREAM_CODEC = TypedDataComponent.STREAM_CODEC .apply(ByteBufCodecs.list()) .map(DataComponentExactPredicate::new, dataComponentExactPredicate -> dataComponentExactPredicate.expectedComponents); public static final DataComponentExactPredicate EMPTY = new DataComponentExactPredicate(List.of()); private final List> expectedComponents; DataComponentExactPredicate(List> expectedComponents) { this.expectedComponents = expectedComponents; } public static DataComponentExactPredicate.Builder builder() { return new DataComponentExactPredicate.Builder(); } public static DataComponentExactPredicate expect(DataComponentType component, T value) { return new DataComponentExactPredicate(List.of(new TypedDataComponent<>(component, value))); } public static DataComponentExactPredicate allOf(DataComponentMap map) { return new DataComponentExactPredicate(ImmutableList.copyOf(map)); } public static DataComponentExactPredicate someOf(DataComponentMap map, DataComponentType... types) { DataComponentExactPredicate.Builder builder = new DataComponentExactPredicate.Builder(); for (DataComponentType dataComponentType : types) { TypedDataComponent typedDataComponent = map.getTyped(dataComponentType); if (typedDataComponent != null) { builder.expect(typedDataComponent); } } return builder.build(); } public boolean isEmpty() { return this.expectedComponents.isEmpty(); } public boolean equals(Object object) { return object instanceof DataComponentExactPredicate dataComponentExactPredicate && this.expectedComponents.equals(dataComponentExactPredicate.expectedComponents); } public int hashCode() { return this.expectedComponents.hashCode(); } public String toString() { return this.expectedComponents.toString(); } public boolean test(DataComponentGetter dataComponentGetter) { for (TypedDataComponent typedDataComponent : this.expectedComponents) { Object object = dataComponentGetter.get(typedDataComponent.type()); if (!Objects.equals(typedDataComponent.value(), object)) { return false; } } return true; } public boolean alwaysMatches() { return this.expectedComponents.isEmpty(); } public DataComponentPatch asPatch() { DataComponentPatch.Builder builder = DataComponentPatch.builder(); for (TypedDataComponent typedDataComponent : this.expectedComponents) { builder.set(typedDataComponent); } return builder.build(); } public static class Builder { private final List> expectedComponents = new ArrayList(); Builder() { } public DataComponentExactPredicate.Builder expect(TypedDataComponent component) { return this.expect(component.type(), component.value()); } public DataComponentExactPredicate.Builder expect(DataComponentType component, T value) { for (TypedDataComponent typedDataComponent : this.expectedComponents) { if (typedDataComponent.type() == component) { throw new IllegalArgumentException("Predicate already has component of type: '" + component + "'"); } } this.expectedComponents.add(new TypedDataComponent<>(component, value)); return this; } public DataComponentExactPredicate build() { return new DataComponentExactPredicate(List.copyOf(this.expectedComponents)); } } }