minecraft-src/net/minecraft/world/entity/ai/goal/BreedGoal.java
2025-07-04 01:41:11 +03:00

89 lines
2.6 KiB
Java

package net.minecraft.world.entity.ai.goal;
import java.util.EnumSet;
import java.util.List;
import net.minecraft.server.level.ServerLevel;
import net.minecraft.world.entity.ai.targeting.TargetingConditions;
import net.minecraft.world.entity.animal.Animal;
import net.minecraft.world.level.Level;
import org.jetbrains.annotations.Nullable;
public class BreedGoal extends Goal {
private static final TargetingConditions PARTNER_TARGETING = TargetingConditions.forNonCombat().range(8.0).ignoreLineOfSight();
protected final Animal animal;
private final Class<? extends Animal> partnerClass;
protected final Level level;
@Nullable
protected Animal partner;
private int loveTime;
private final double speedModifier;
public BreedGoal(Animal animal, double speedModifier) {
this(animal, speedModifier, animal.getClass());
}
public BreedGoal(Animal animal, double speedModifier, Class<? extends Animal> partnerClass) {
this.animal = animal;
this.level = animal.level();
this.partnerClass = partnerClass;
this.speedModifier = speedModifier;
this.setFlags(EnumSet.of(Goal.Flag.MOVE, Goal.Flag.LOOK));
}
@Override
public boolean canUse() {
if (!this.animal.isInLove()) {
return false;
} else {
this.partner = this.getFreePartner();
return this.partner != null;
}
}
@Override
public boolean canContinueToUse() {
return this.partner.isAlive() && this.partner.isInLove() && this.loveTime < 60 && !this.partner.isPanicking();
}
@Override
public void stop() {
this.partner = null;
this.loveTime = 0;
}
@Override
public void tick() {
this.animal.getLookControl().setLookAt(this.partner, 10.0F, this.animal.getMaxHeadXRot());
this.animal.getNavigation().moveTo(this.partner, this.speedModifier);
this.loveTime++;
if (this.loveTime >= this.adjustedTickDelay(60) && this.animal.distanceToSqr(this.partner) < 9.0) {
this.breed();
}
}
/**
* Loops through nearby animals and finds another animal of the same type that can be mated with. Returns the first valid mate found.
*/
@Nullable
private Animal getFreePartner() {
List<? extends Animal> list = this.level.getNearbyEntities(this.partnerClass, PARTNER_TARGETING, this.animal, this.animal.getBoundingBox().inflate(8.0));
double d = Double.MAX_VALUE;
Animal animal = null;
for (Animal animal2 : list) {
if (this.animal.canMate(animal2) && !animal2.isPanicking() && this.animal.distanceToSqr(animal2) < d) {
animal = animal2;
d = this.animal.distanceToSqr(animal2);
}
}
return animal;
}
/**
* Spawns a baby animal of the same type.
*/
protected void breed() {
this.animal.spawnChildFromBreeding((ServerLevel)this.level, this.partner);
}
}