89 lines
2.6 KiB
Java
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);
|
|
}
|
|
}
|