package net.minecraft.advancements.critereon; import com.mojang.serialization.Codec; import com.mojang.serialization.MapCodec; import com.mojang.serialization.codecs.RecordCodecBuilder; import java.util.Optional; import java.util.function.Function; import net.minecraft.core.Holder; import net.minecraft.core.HolderSet; import net.minecraft.core.Registry; import net.minecraft.core.RegistryCodecs; import net.minecraft.core.registries.BuiltInRegistries; import net.minecraft.core.registries.Registries; import net.minecraft.resources.ResourceKey; import net.minecraft.server.level.ServerLevel; import net.minecraft.world.entity.Entity; import net.minecraft.world.entity.animal.Cat; import net.minecraft.world.entity.animal.CatVariant; import net.minecraft.world.entity.animal.Fox; import net.minecraft.world.entity.animal.FrogVariant; import net.minecraft.world.entity.animal.MushroomCow; import net.minecraft.world.entity.animal.Parrot; import net.minecraft.world.entity.animal.Rabbit; import net.minecraft.world.entity.animal.TropicalFish; import net.minecraft.world.entity.animal.Wolf; import net.minecraft.world.entity.animal.WolfVariant; import net.minecraft.world.entity.animal.axolotl.Axolotl; import net.minecraft.world.entity.animal.frog.Frog; import net.minecraft.world.entity.animal.horse.Horse; import net.minecraft.world.entity.animal.horse.Llama; import net.minecraft.world.entity.animal.horse.Variant; import net.minecraft.world.entity.decoration.Painting; import net.minecraft.world.entity.decoration.PaintingVariant; import net.minecraft.world.entity.npc.VillagerDataHolder; import net.minecraft.world.entity.npc.VillagerType; import net.minecraft.world.entity.vehicle.Boat; import net.minecraft.world.phys.Vec3; import org.jetbrains.annotations.Nullable; public class EntitySubPredicates { public static final MapCodec LIGHTNING = register("lightning", LightningBoltPredicate.CODEC); public static final MapCodec FISHING_HOOK = register("fishing_hook", FishingHookPredicate.CODEC); public static final MapCodec PLAYER = register("player", PlayerPredicate.CODEC); public static final MapCodec SLIME = register("slime", SlimePredicate.CODEC); public static final MapCodec RAIDER = register("raider", RaiderPredicate.CODEC); public static final EntitySubPredicates.EntityVariantPredicateType AXOLOTL = register( "axolotl", EntitySubPredicates.EntityVariantPredicateType.create( Axolotl.Variant.CODEC, entity -> entity instanceof Axolotl axolotl ? Optional.of(axolotl.getVariant()) : Optional.empty() ) ); public static final EntitySubPredicates.EntityVariantPredicateType BOAT = register( "boat", EntitySubPredicates.EntityVariantPredicateType.create( Boat.Type.CODEC, entity -> entity instanceof Boat boat ? Optional.of(boat.getVariant()) : Optional.empty() ) ); public static final EntitySubPredicates.EntityVariantPredicateType FOX = register( "fox", EntitySubPredicates.EntityVariantPredicateType.create(Fox.Type.CODEC, entity -> entity instanceof Fox fox ? Optional.of(fox.getVariant()) : Optional.empty()) ); public static final EntitySubPredicates.EntityVariantPredicateType MOOSHROOM = register( "mooshroom", EntitySubPredicates.EntityVariantPredicateType.create( MushroomCow.MushroomType.CODEC, entity -> entity instanceof MushroomCow mushroomCow ? Optional.of(mushroomCow.getVariant()) : Optional.empty() ) ); public static final EntitySubPredicates.EntityVariantPredicateType RABBIT = register( "rabbit", EntitySubPredicates.EntityVariantPredicateType.create( Rabbit.Variant.CODEC, entity -> entity instanceof Rabbit rabbit ? Optional.of(rabbit.getVariant()) : Optional.empty() ) ); public static final EntitySubPredicates.EntityVariantPredicateType HORSE = register( "horse", EntitySubPredicates.EntityVariantPredicateType.create( Variant.CODEC, entity -> entity instanceof Horse horse ? Optional.of(horse.getVariant()) : Optional.empty() ) ); public static final EntitySubPredicates.EntityVariantPredicateType LLAMA = register( "llama", EntitySubPredicates.EntityVariantPredicateType.create( Llama.Variant.CODEC, entity -> entity instanceof Llama llama ? Optional.of(llama.getVariant()) : Optional.empty() ) ); public static final EntitySubPredicates.EntityVariantPredicateType VILLAGER = register( "villager", EntitySubPredicates.EntityVariantPredicateType.create( BuiltInRegistries.VILLAGER_TYPE.byNameCodec(), entity -> entity instanceof VillagerDataHolder villagerDataHolder ? Optional.of(villagerDataHolder.getVariant()) : Optional.empty() ) ); public static final EntitySubPredicates.EntityVariantPredicateType PARROT = register( "parrot", EntitySubPredicates.EntityVariantPredicateType.create( Parrot.Variant.CODEC, entity -> entity instanceof Parrot parrot ? Optional.of(parrot.getVariant()) : Optional.empty() ) ); public static final EntitySubPredicates.EntityVariantPredicateType TROPICAL_FISH = register( "tropical_fish", EntitySubPredicates.EntityVariantPredicateType.create( TropicalFish.Pattern.CODEC, entity -> entity instanceof TropicalFish tropicalFish ? Optional.of(tropicalFish.getVariant()) : Optional.empty() ) ); public static final EntitySubPredicates.EntityHolderVariantPredicateType PAINTING = register( "painting", EntitySubPredicates.EntityHolderVariantPredicateType.create( Registries.PAINTING_VARIANT, entity -> entity instanceof Painting painting ? Optional.of(painting.getVariant()) : Optional.empty() ) ); public static final EntitySubPredicates.EntityHolderVariantPredicateType CAT = register( "cat", EntitySubPredicates.EntityHolderVariantPredicateType.create( Registries.CAT_VARIANT, entity -> entity instanceof Cat cat ? Optional.of(cat.getVariant()) : Optional.empty() ) ); public static final EntitySubPredicates.EntityHolderVariantPredicateType FROG = register( "frog", EntitySubPredicates.EntityHolderVariantPredicateType.create( Registries.FROG_VARIANT, entity -> entity instanceof Frog frog ? Optional.of(frog.getVariant()) : Optional.empty() ) ); public static final EntitySubPredicates.EntityHolderVariantPredicateType WOLF = register( "wolf", EntitySubPredicates.EntityHolderVariantPredicateType.create( Registries.WOLF_VARIANT, entity -> entity instanceof Wolf wolf ? Optional.of(wolf.getVariant()) : Optional.empty() ) ); private static MapCodec register(String name, MapCodec codec) { return Registry.register(BuiltInRegistries.ENTITY_SUB_PREDICATE_TYPE, name, codec); } private static EntitySubPredicates.EntityVariantPredicateType register(String name, EntitySubPredicates.EntityVariantPredicateType predicateType) { Registry.register(BuiltInRegistries.ENTITY_SUB_PREDICATE_TYPE, name, predicateType.codec); return predicateType; } private static EntitySubPredicates.EntityHolderVariantPredicateType register( String name, EntitySubPredicates.EntityHolderVariantPredicateType predicateType ) { Registry.register(BuiltInRegistries.ENTITY_SUB_PREDICATE_TYPE, name, predicateType.codec); return predicateType; } public static MapCodec bootstrap(Registry> registry) { return LIGHTNING; } public static EntitySubPredicate catVariant(Holder catVariant) { return CAT.createPredicate(HolderSet.direct(catVariant)); } public static EntitySubPredicate frogVariant(Holder frogVariant) { return FROG.createPredicate(HolderSet.direct(frogVariant)); } public static EntitySubPredicate wolfVariant(HolderSet wolfVariant) { return WOLF.createPredicate(wolfVariant); } public static class EntityHolderVariantPredicateType { final MapCodec.Instance> codec; final Function>> getter; public static EntitySubPredicates.EntityHolderVariantPredicateType create( ResourceKey> registryKey, Function>> getter ) { return new EntitySubPredicates.EntityHolderVariantPredicateType<>(registryKey, getter); } public EntityHolderVariantPredicateType(ResourceKey> registryKey, Function>> getter) { this.getter = getter; this.codec = RecordCodecBuilder.mapCodec( instance -> instance.group(RegistryCodecs.homogeneousList(registryKey).fieldOf("variant").forGetter(instancex -> instancex.variants)) .apply(instance, holderSet -> new EntitySubPredicates.EntityHolderVariantPredicateType.Instance(holderSet)) ); } public EntitySubPredicate createPredicate(HolderSet variants) { return new EntitySubPredicates.EntityHolderVariantPredicateType.Instance(variants); } class Instance implements EntitySubPredicate { final HolderSet variants; Instance(final HolderSet variants) { this.variants = variants; } @Override public MapCodec.Instance> codec() { return EntityHolderVariantPredicateType.this.codec; } @Override public boolean matches(Entity entity, ServerLevel level, @Nullable Vec3 position) { return ((Optional)EntityHolderVariantPredicateType.this.getter.apply(entity)).filter(this.variants::contains).isPresent(); } } } public static class EntityVariantPredicateType { final MapCodec.Instance> codec; final Function> getter; public static EntitySubPredicates.EntityVariantPredicateType create(Registry variantRegistry, Function> getter) { return new EntitySubPredicates.EntityVariantPredicateType<>(variantRegistry.byNameCodec(), getter); } public static EntitySubPredicates.EntityVariantPredicateType create(Codec codec, Function> getter) { return new EntitySubPredicates.EntityVariantPredicateType<>(codec, getter); } public EntityVariantPredicateType(Codec codec, Function> getter) { this.getter = getter; this.codec = RecordCodecBuilder.mapCodec( instance -> instance.group(codec.fieldOf("variant").forGetter(instancex -> instancex.variant)) .apply(instance, object -> new EntitySubPredicates.EntityVariantPredicateType.Instance(object)) ); } public EntitySubPredicate createPredicate(V variant) { return new EntitySubPredicates.EntityVariantPredicateType.Instance(variant); } class Instance implements EntitySubPredicate { final V variant; Instance(final V variant) { this.variant = variant; } @Override public MapCodec.Instance> codec() { return EntityVariantPredicateType.this.codec; } @Override public boolean matches(Entity entity, ServerLevel level, @Nullable Vec3 position) { return ((Optional)EntityVariantPredicateType.this.getter.apply(entity)).filter(this.variant::equals).isPresent(); } } } }