100 lines
3 KiB
Java
100 lines
3 KiB
Java
package net.minecraft.world.entity.ai.targeting;
|
|
|
|
import net.minecraft.server.level.ServerLevel;
|
|
import net.minecraft.world.Difficulty;
|
|
import net.minecraft.world.entity.LivingEntity;
|
|
import net.minecraft.world.entity.Mob;
|
|
import org.jetbrains.annotations.Nullable;
|
|
|
|
public class TargetingConditions {
|
|
public static final TargetingConditions DEFAULT = forCombat();
|
|
private static final double MIN_VISIBILITY_DISTANCE_FOR_INVISIBLE_TARGET = 2.0;
|
|
private final boolean isCombat;
|
|
private double range = -1.0;
|
|
private boolean checkLineOfSight = true;
|
|
private boolean testInvisible = true;
|
|
@Nullable
|
|
private TargetingConditions.Selector selector;
|
|
|
|
private TargetingConditions(boolean isCombat) {
|
|
this.isCombat = isCombat;
|
|
}
|
|
|
|
public static TargetingConditions forCombat() {
|
|
return new TargetingConditions(true);
|
|
}
|
|
|
|
public static TargetingConditions forNonCombat() {
|
|
return new TargetingConditions(false);
|
|
}
|
|
|
|
public TargetingConditions copy() {
|
|
TargetingConditions targetingConditions = this.isCombat ? forCombat() : forNonCombat();
|
|
targetingConditions.range = this.range;
|
|
targetingConditions.checkLineOfSight = this.checkLineOfSight;
|
|
targetingConditions.testInvisible = this.testInvisible;
|
|
targetingConditions.selector = this.selector;
|
|
return targetingConditions;
|
|
}
|
|
|
|
public TargetingConditions range(double distance) {
|
|
this.range = distance;
|
|
return this;
|
|
}
|
|
|
|
public TargetingConditions ignoreLineOfSight() {
|
|
this.checkLineOfSight = false;
|
|
return this;
|
|
}
|
|
|
|
public TargetingConditions ignoreInvisibilityTesting() {
|
|
this.testInvisible = false;
|
|
return this;
|
|
}
|
|
|
|
public TargetingConditions selector(@Nullable TargetingConditions.Selector selector) {
|
|
this.selector = selector;
|
|
return this;
|
|
}
|
|
|
|
public boolean test(ServerLevel serverLevel, @Nullable LivingEntity livingEntity, LivingEntity livingEntity2) {
|
|
if (livingEntity == livingEntity2) {
|
|
return false;
|
|
} else if (!livingEntity2.canBeSeenByAnyone()) {
|
|
return false;
|
|
} else if (this.selector != null && !this.selector.test(livingEntity2, serverLevel)) {
|
|
return false;
|
|
} else {
|
|
if (livingEntity == null) {
|
|
if (this.isCombat && (!livingEntity2.canBeSeenAsEnemy() || serverLevel.getDifficulty() == Difficulty.PEACEFUL)) {
|
|
return false;
|
|
}
|
|
} else {
|
|
if (this.isCombat
|
|
&& (!livingEntity.canAttack(livingEntity2) || !livingEntity.canAttackType(livingEntity2.getType()) || livingEntity.isAlliedTo(livingEntity2))) {
|
|
return false;
|
|
}
|
|
|
|
if (this.range > 0.0) {
|
|
double d = this.testInvisible ? livingEntity2.getVisibilityPercent(livingEntity) : 1.0;
|
|
double e = Math.max(this.range * d, 2.0);
|
|
double f = livingEntity.distanceToSqr(livingEntity2.getX(), livingEntity2.getY(), livingEntity2.getZ());
|
|
if (f > e * e) {
|
|
return false;
|
|
}
|
|
}
|
|
|
|
if (this.checkLineOfSight && livingEntity instanceof Mob mob && !mob.getSensing().hasLineOfSight(livingEntity2)) {
|
|
return false;
|
|
}
|
|
}
|
|
|
|
return true;
|
|
}
|
|
}
|
|
|
|
@FunctionalInterface
|
|
public interface Selector {
|
|
boolean test(LivingEntity livingEntity, ServerLevel serverLevel);
|
|
}
|
|
}
|