package net.minecraft.advancements.critereon; import com.mojang.serialization.Codec; import com.mojang.serialization.MapCodec; import com.mojang.serialization.codecs.RecordCodecBuilder; import com.mojang.serialization.codecs.RecordCodecBuilder.Instance; import java.util.List; import java.util.Optional; import java.util.stream.Stream; import javax.annotation.Nullable; import net.minecraft.core.HolderGetter; import net.minecraft.core.component.DataComponentGetter; import net.minecraft.server.level.ServerLevel; import net.minecraft.server.level.ServerPlayer; import net.minecraft.tags.TagKey; import net.minecraft.util.ExtraCodecs; import net.minecraft.world.entity.Entity; import net.minecraft.world.entity.EntityType; import net.minecraft.world.entity.Mob; import net.minecraft.world.level.storage.loot.LootContext; import net.minecraft.world.level.storage.loot.LootParams; import net.minecraft.world.level.storage.loot.parameters.LootContextParamSets; import net.minecraft.world.level.storage.loot.parameters.LootContextParams; import net.minecraft.world.level.storage.loot.predicates.LootItemCondition; import net.minecraft.world.level.storage.loot.predicates.LootItemEntityPropertyCondition; import net.minecraft.world.phys.Vec3; import net.minecraft.world.scores.Team; public record EntityPredicate( Optional entityType, Optional distanceToPlayer, Optional movement, EntityPredicate.LocationWrapper location, Optional effects, Optional nbt, Optional flags, Optional equipment, Optional subPredicate, Optional periodicTick, Optional vehicle, Optional passenger, Optional targetedEntity, Optional team, Optional slots, DataComponentMatchers components ) { public static final Codec CODEC = Codec.recursive( "EntityPredicate", p_296121_ -> RecordCodecBuilder.create( p_340757_ -> p_340757_.group( EntityTypePredicate.CODEC.optionalFieldOf("type").forGetter(EntityPredicate::entityType), DistancePredicate.CODEC.optionalFieldOf("distance").forGetter(EntityPredicate::distanceToPlayer), MovementPredicate.CODEC.optionalFieldOf("movement").forGetter(EntityPredicate::movement), EntityPredicate.LocationWrapper.CODEC.forGetter(EntityPredicate::location), MobEffectsPredicate.CODEC.optionalFieldOf("effects").forGetter(EntityPredicate::effects), NbtPredicate.CODEC.optionalFieldOf("nbt").forGetter(EntityPredicate::nbt), EntityFlagsPredicate.CODEC.optionalFieldOf("flags").forGetter(EntityPredicate::flags), EntityEquipmentPredicate.CODEC.optionalFieldOf("equipment").forGetter(EntityPredicate::equipment), EntitySubPredicate.CODEC.optionalFieldOf("type_specific").forGetter(EntityPredicate::subPredicate), ExtraCodecs.POSITIVE_INT.optionalFieldOf("periodic_tick").forGetter(EntityPredicate::periodicTick), p_296121_.optionalFieldOf("vehicle").forGetter(EntityPredicate::vehicle), p_296121_.optionalFieldOf("passenger").forGetter(EntityPredicate::passenger), p_296121_.optionalFieldOf("targeted_entity").forGetter(EntityPredicate::targetedEntity), Codec.STRING.optionalFieldOf("team").forGetter(EntityPredicate::team), SlotsPredicate.CODEC.optionalFieldOf("slots").forGetter(EntityPredicate::slots), DataComponentMatchers.CODEC.forGetter(EntityPredicate::components) ) .apply(p_340757_, EntityPredicate::new) ) ); public static final Codec ADVANCEMENT_CODEC = Codec.withAlternative(ContextAwarePredicate.CODEC, CODEC, EntityPredicate::wrap); public static ContextAwarePredicate wrap(EntityPredicate.Builder p_298584_) { return wrap(p_298584_.build()); } public static Optional wrap(Optional p_300980_) { return p_300980_.map(EntityPredicate::wrap); } public static List wrap(EntityPredicate.Builder... p_299692_) { return Stream.of(p_299692_).map(EntityPredicate::wrap).toList(); } public static ContextAwarePredicate wrap(EntityPredicate p_286570_) { LootItemCondition lootitemcondition = LootItemEntityPropertyCondition.hasProperties(LootContext.EntityTarget.THIS, p_286570_).build(); return new ContextAwarePredicate(List.of(lootitemcondition)); } public boolean matches(ServerPlayer p_36612_, @Nullable Entity p_36613_) { return this.matches(p_36612_.serverLevel(), p_36612_.position(), p_36613_); } public boolean matches(ServerLevel p_36608_, @Nullable Vec3 p_36609_, @Nullable Entity p_36610_) { if (p_36610_ == null) { return false; } else if (this.entityType.isPresent() && !this.entityType.get().matches(p_36610_.getType())) { return false; } else { if (p_36609_ == null) { if (this.distanceToPlayer.isPresent()) { return false; } } else if (this.distanceToPlayer.isPresent() && !this.distanceToPlayer .get() .matches(p_36609_.x, p_36609_.y, p_36609_.z, p_36610_.getX(), p_36610_.getY(), p_36610_.getZ())) { return false; } if (this.movement.isPresent()) { Vec3 vec3 = p_36610_.getKnownMovement(); Vec3 vec31 = vec3.scale(20.0); if (!this.movement.get().matches(vec31.x, vec31.y, vec31.z, p_36610_.fallDistance)) { return false; } } if (this.location.located.isPresent() && !this.location.located.get().matches(p_36608_, p_36610_.getX(), p_36610_.getY(), p_36610_.getZ())) { return false; } else { if (this.location.steppingOn.isPresent()) { Vec3 vec32 = Vec3.atCenterOf(p_36610_.getOnPos()); if (!p_36610_.onGround() || !this.location.steppingOn.get().matches(p_36608_, vec32.x(), vec32.y(), vec32.z())) { return false; } } if (this.location.affectsMovement.isPresent()) { Vec3 vec33 = Vec3.atCenterOf(p_36610_.getBlockPosBelowThatAffectsMyMovement()); if (!this.location.affectsMovement.get().matches(p_36608_, vec33.x(), vec33.y(), vec33.z())) { return false; } } if (this.effects.isPresent() && !this.effects.get().matches(p_36610_)) { return false; } else if (this.flags.isPresent() && !this.flags.get().matches(p_36610_)) { return false; } else if (this.equipment.isPresent() && !this.equipment.get().matches(p_36610_)) { return false; } else if (this.subPredicate.isPresent() && !this.subPredicate.get().matches(p_36610_, p_36608_, p_36609_)) { return false; } else if (this.vehicle.isPresent() && !this.vehicle.get().matches(p_36608_, p_36609_, p_36610_.getVehicle())) { return false; } else if (this.passenger.isPresent() && p_36610_.getPassengers().stream().noneMatch(p_296124_ -> this.passenger.get().matches(p_36608_, p_36609_, p_296124_))) { return false; } else if (this.targetedEntity.isPresent() && !this.targetedEntity.get().matches(p_36608_, p_36609_, p_36610_ instanceof Mob ? ((Mob)p_36610_).getTarget() : null)) { return false; } else if (this.periodicTick.isPresent() && p_36610_.tickCount % this.periodicTick.get() != 0) { return false; } else { if (this.team.isPresent()) { Team team = p_36610_.getTeam(); if (team == null || !this.team.get().equals(team.getName())) { return false; } } if (this.slots.isPresent() && !this.slots.get().matches(p_36610_)) { return false; } else { return !this.components.test((DataComponentGetter)p_36610_) ? false : this.nbt.isEmpty() || this.nbt.get().matches(p_36610_); } } } } } public static LootContext createContext(ServerPlayer p_36617_, Entity p_36618_) { LootParams lootparams = new LootParams.Builder(p_36617_.serverLevel()) .withParameter(LootContextParams.THIS_ENTITY, p_36618_) .withParameter(LootContextParams.ORIGIN, p_36617_.position()) .create(LootContextParamSets.ADVANCEMENT_ENTITY); return new LootContext.Builder(lootparams).create(Optional.empty()); } public static class Builder { private Optional entityType = Optional.empty(); private Optional distanceToPlayer = Optional.empty(); private Optional movement = Optional.empty(); private Optional located = Optional.empty(); private Optional steppingOnLocation = Optional.empty(); private Optional movementAffectedBy = Optional.empty(); private Optional effects = Optional.empty(); private Optional nbt = Optional.empty(); private Optional flags = Optional.empty(); private Optional equipment = Optional.empty(); private Optional subPredicate = Optional.empty(); private Optional periodicTick = Optional.empty(); private Optional vehicle = Optional.empty(); private Optional passenger = Optional.empty(); private Optional targetedEntity = Optional.empty(); private Optional team = Optional.empty(); private Optional slots = Optional.empty(); private DataComponentMatchers components = DataComponentMatchers.ANY; public static EntityPredicate.Builder entity() { return new EntityPredicate.Builder(); } public EntityPredicate.Builder of(HolderGetter> p_370143_, EntityType p_36637_) { this.entityType = Optional.of(EntityTypePredicate.of(p_370143_, p_36637_)); return this; } public EntityPredicate.Builder of(HolderGetter> p_361882_, TagKey> p_204078_) { this.entityType = Optional.of(EntityTypePredicate.of(p_361882_, p_204078_)); return this; } public EntityPredicate.Builder entityType(EntityTypePredicate p_36647_) { this.entityType = Optional.of(p_36647_); return this; } public EntityPredicate.Builder distance(DistancePredicate p_36639_) { this.distanceToPlayer = Optional.of(p_36639_); return this; } public EntityPredicate.Builder moving(MovementPredicate p_342759_) { this.movement = Optional.of(p_342759_); return this; } public EntityPredicate.Builder located(LocationPredicate.Builder p_297650_) { this.located = Optional.of(p_297650_.build()); return this; } public EntityPredicate.Builder steppingOn(LocationPredicate.Builder p_298486_) { this.steppingOnLocation = Optional.of(p_298486_.build()); return this; } public EntityPredicate.Builder movementAffectedBy(LocationPredicate.Builder p_344369_) { this.movementAffectedBy = Optional.of(p_344369_.build()); return this; } public EntityPredicate.Builder effects(MobEffectsPredicate.Builder p_300139_) { this.effects = p_300139_.build(); return this; } public EntityPredicate.Builder nbt(NbtPredicate p_36655_) { this.nbt = Optional.of(p_36655_); return this; } public EntityPredicate.Builder flags(EntityFlagsPredicate.Builder p_300535_) { this.flags = Optional.of(p_300535_.build()); return this; } public EntityPredicate.Builder equipment(EntityEquipmentPredicate.Builder p_297462_) { this.equipment = Optional.of(p_297462_.build()); return this; } public EntityPredicate.Builder equipment(EntityEquipmentPredicate p_36641_) { this.equipment = Optional.of(p_36641_); return this; } public EntityPredicate.Builder subPredicate(EntitySubPredicate p_218801_) { this.subPredicate = Optional.of(p_218801_); return this; } public EntityPredicate.Builder periodicTick(int p_343808_) { this.periodicTick = Optional.of(p_343808_); return this; } public EntityPredicate.Builder vehicle(EntityPredicate.Builder p_300159_) { this.vehicle = Optional.of(p_300159_.build()); return this; } public EntityPredicate.Builder passenger(EntityPredicate.Builder p_297891_) { this.passenger = Optional.of(p_297891_.build()); return this; } public EntityPredicate.Builder targetedEntity(EntityPredicate.Builder p_298127_) { this.targetedEntity = Optional.of(p_298127_.build()); return this; } public EntityPredicate.Builder team(String p_36659_) { this.team = Optional.of(p_36659_); return this; } public EntityPredicate.Builder slots(SlotsPredicate p_330666_) { this.slots = Optional.of(p_330666_); return this; } public EntityPredicate.Builder components(DataComponentMatchers p_395894_) { this.components = p_395894_; return this; } public EntityPredicate build() { return new EntityPredicate( this.entityType, this.distanceToPlayer, this.movement, new EntityPredicate.LocationWrapper(this.located, this.steppingOnLocation, this.movementAffectedBy), this.effects, this.nbt, this.flags, this.equipment, this.subPredicate, this.periodicTick, this.vehicle, this.passenger, this.targetedEntity, this.team, this.slots, this.components ); } } public record LocationWrapper(Optional located, Optional steppingOn, Optional affectsMovement) { public static final MapCodec CODEC = RecordCodecBuilder.mapCodec( p_343798_ -> p_343798_.group( LocationPredicate.CODEC.optionalFieldOf("location").forGetter(EntityPredicate.LocationWrapper::located), LocationPredicate.CODEC.optionalFieldOf("stepping_on").forGetter(EntityPredicate.LocationWrapper::steppingOn), LocationPredicate.CODEC.optionalFieldOf("movement_affected_by").forGetter(EntityPredicate.LocationWrapper::affectsMovement) ) .apply(p_343798_, EntityPredicate.LocationWrapper::new) ); } }