-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge remote-tracking branch 'origin/master—' into master—
- Loading branch information
1 parent
c79f9d0
commit 5011f70
Showing
10 changed files
with
685 additions
and
147 deletions.
There are no files selected for viewing
98 changes: 98 additions & 0 deletions
98
src/main/java/com/equilibrium/entity/goal/AdvanceActiveTargetGoal.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,98 @@ | ||
package com.equilibrium.entity.goal; | ||
|
||
import java.util.EnumSet; | ||
import java.util.function.Predicate; | ||
import net.minecraft.entity.LivingEntity; | ||
import net.minecraft.entity.ai.TargetPredicate; | ||
import net.minecraft.entity.ai.goal.Goal; | ||
import net.minecraft.entity.ai.goal.TrackTargetGoal; | ||
import net.minecraft.entity.mob.MobEntity; | ||
import net.minecraft.entity.player.PlayerEntity; | ||
import net.minecraft.server.network.ServerPlayerEntity; | ||
import net.minecraft.util.math.Box; | ||
import org.jetbrains.annotations.Nullable; | ||
|
||
/** | ||
* A target goal that finds a target by entity class when the goal starts. | ||
*/ | ||
public class AdvanceActiveTargetGoal<T extends LivingEntity> extends TrackTargetGoal { | ||
private static final int DEFAULT_RECIPROCAL_CHANCE = 10; | ||
protected final Class<T> targetClass; | ||
/** | ||
* The reciprocal of chance to actually search for a target on every tick | ||
* when this goal is not started. This is also the average number of ticks | ||
* between each search (as in a poisson distribution). | ||
*/ | ||
protected final int reciprocalChance; | ||
@Nullable | ||
protected LivingEntity targetEntity; | ||
protected AdvanceTargetPredicate targetPredicate; | ||
|
||
public AdvanceActiveTargetGoal(MobEntity mob, Class<T> targetClass, boolean checkVisibility) { | ||
this(mob, targetClass, 10, checkVisibility, false, null); | ||
} | ||
|
||
public AdvanceActiveTargetGoal(MobEntity mob, Class<T> targetClass, boolean checkVisibility, Predicate<LivingEntity> targetPredicate) { | ||
this(mob, targetClass, 10, checkVisibility, false, targetPredicate); | ||
} | ||
|
||
public AdvanceActiveTargetGoal(MobEntity mob, Class<T> targetClass, boolean checkVisibility, boolean checkCanNavigate) { | ||
this(mob, targetClass, 10, checkVisibility, checkCanNavigate, null); | ||
} | ||
|
||
public AdvanceActiveTargetGoal( | ||
MobEntity mob, | ||
Class<T> targetClass, | ||
int reciprocalChance, | ||
boolean checkVisibility, | ||
boolean checkCanNavigate, | ||
@Nullable Predicate<LivingEntity> targetPredicate | ||
) { | ||
super(mob, checkVisibility, checkCanNavigate); | ||
this.targetClass = targetClass; | ||
this.reciprocalChance = toGoalTicks(reciprocalChance); | ||
this.setControls(EnumSet.of(Goal.Control.TARGET)); | ||
this.targetPredicate = AdvanceTargetPredicate.createAttackable().setBaseMaxDistance(this.getFollowRange()).setPredicate(targetPredicate); | ||
} | ||
|
||
@Override | ||
public boolean canStart() { | ||
if (this.reciprocalChance > 0 && this.mob.getRandom().nextInt(this.reciprocalChance) != 0) { | ||
return false; | ||
} else { | ||
this.findClosestTarget(); | ||
return this.targetEntity != null; | ||
} | ||
} | ||
|
||
protected Box getSearchBox(double distance) { | ||
return this.mob.getBoundingBox().expand(distance, 4.0, distance); | ||
} | ||
|
||
protected void findClosestTarget() { | ||
if (this.targetClass != PlayerEntity.class && this.targetClass != ServerPlayerEntity.class) { | ||
this.targetEntity = this.mob | ||
.getWorld() | ||
.getClosestEntity( | ||
this.mob.getWorld().getEntitiesByClass(this.targetClass, this.getSearchBox(this.getFollowRange()), livingEntity -> true), | ||
this.targetPredicate, | ||
this.mob, | ||
this.mob.getX(), | ||
this.mob.getEyeY(), | ||
this.mob.getZ() | ||
); | ||
} else { | ||
this.targetEntity = this.mob.getWorld().getClosestPlayer(this.targetPredicate, this.mob, this.mob.getX(), this.mob.getEyeY(), this.mob.getZ()); | ||
} | ||
} | ||
|
||
@Override | ||
public void start() { | ||
this.mob.setTarget(this.targetEntity); | ||
super.start(); | ||
} | ||
|
||
public void setTargetEntity(@Nullable LivingEntity targetEntity) { | ||
this.targetEntity = targetEntity; | ||
} | ||
} |
133 changes: 133 additions & 0 deletions
133
src/main/java/com/equilibrium/entity/goal/AdvanceTargetPredicate.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,133 @@ | ||
package com.equilibrium.entity.goal; | ||
|
||
import java.util.function.Predicate; | ||
|
||
import com.equilibrium.tags.ModBlockTags; | ||
import net.minecraft.block.BlockState; | ||
import net.minecraft.block.Blocks; | ||
import net.minecraft.entity.LivingEntity; | ||
import net.minecraft.entity.ai.TargetPredicate; | ||
import net.minecraft.entity.attribute.EntityAttributes; | ||
import net.minecraft.entity.mob.MobEntity; | ||
import net.minecraft.util.hit.BlockHitResult; | ||
import net.minecraft.util.math.BlockPos; | ||
import net.minecraft.util.math.Vec3d; | ||
import net.minecraft.world.Difficulty; | ||
import net.minecraft.world.RaycastContext; | ||
import net.minecraft.world.World; | ||
import org.jetbrains.annotations.Nullable; | ||
|
||
public class AdvanceTargetPredicate extends TargetPredicate { | ||
public static final AdvanceTargetPredicate DEFAULT = createAttackable(); | ||
private static final double MIN_DISTANCE = 2.0; | ||
private final boolean attackable; | ||
private double baseMaxDistance = -1.0; | ||
private boolean respectsVisibility = true; | ||
private boolean useDistanceScalingFactor = true; | ||
@Nullable | ||
private Predicate<LivingEntity> predicate; | ||
|
||
private AdvanceTargetPredicate(boolean attackable) { | ||
super(attackable); | ||
this.attackable = attackable; | ||
} | ||
|
||
public static AdvanceTargetPredicate createAttackable() { | ||
return new AdvanceTargetPredicate(true); | ||
} | ||
|
||
public static AdvanceTargetPredicate createNonAttackable() { | ||
return new AdvanceTargetPredicate(false); | ||
} | ||
|
||
public AdvanceTargetPredicate copy() { | ||
|
||
AdvanceTargetPredicate advanceTargetPredicate = this.attackable ? createAttackable() : createNonAttackable(); | ||
advanceTargetPredicate.baseMaxDistance = this.baseMaxDistance; | ||
advanceTargetPredicate.respectsVisibility = this.respectsVisibility; | ||
advanceTargetPredicate.useDistanceScalingFactor = this.useDistanceScalingFactor; | ||
advanceTargetPredicate.predicate = this.predicate; | ||
return advanceTargetPredicate; | ||
} | ||
|
||
public AdvanceTargetPredicate setBaseMaxDistance(double baseMaxDistance) { | ||
this.baseMaxDistance = baseMaxDistance; | ||
return this; | ||
} | ||
|
||
public AdvanceTargetPredicate ignoreVisibility() { | ||
this.respectsVisibility = false; | ||
return this; | ||
} | ||
|
||
public AdvanceTargetPredicate ignoreDistanceScalingFactor() { | ||
this.useDistanceScalingFactor = false; | ||
return this; | ||
} | ||
|
||
public AdvanceTargetPredicate setPredicate(@Nullable Predicate<LivingEntity> predicate) { | ||
this.predicate = predicate; | ||
return this; | ||
} | ||
|
||
public boolean test(@Nullable LivingEntity baseEntity, LivingEntity targetEntity) { | ||
if (baseEntity == targetEntity) { | ||
return false; | ||
} else if (!targetEntity.isPartOfGame()) { | ||
return false; | ||
} else if (this.predicate != null && !this.predicate.test(targetEntity)) { | ||
return false; | ||
} else { | ||
if (baseEntity == null) { | ||
if (this.attackable && (!targetEntity.canTakeDamage() || targetEntity.getWorld().getDifficulty() == Difficulty.PEACEFUL)) { | ||
return false; | ||
} | ||
} else { | ||
if (this.attackable && (!baseEntity.canTarget(targetEntity) || !baseEntity.canTarget(targetEntity.getType()) || baseEntity.isTeammate(targetEntity))) { | ||
return false; | ||
} | ||
|
||
if (this.baseMaxDistance > 0.0) { | ||
double d = this.useDistanceScalingFactor ? targetEntity.getAttackDistanceScalingFactor(baseEntity) : 1.0; | ||
double e = Math.max(this.baseMaxDistance * d, 2.0); | ||
double f = baseEntity.squaredDistanceTo(targetEntity.getX(), targetEntity.getY(), targetEntity.getZ()); | ||
if (f > e * e) { | ||
return false; | ||
} | ||
} | ||
|
||
if (this.respectsVisibility && baseEntity instanceof MobEntity mobEntity && !canSeeThroughTransparentBlocks(mobEntity, targetEntity)) { | ||
return false; | ||
} | ||
} | ||
|
||
return true; | ||
} | ||
} | ||
private boolean canSeeThroughTransparentBlocks(MobEntity mobEntity, LivingEntity targetEntity) { | ||
World world = mobEntity.getWorld(); | ||
Vec3d startPos = new Vec3d(mobEntity.getX(), mobEntity.getEyeY(), mobEntity.getZ()); | ||
Vec3d endPos = new Vec3d(targetEntity.getX(), targetEntity.getEyeY(), targetEntity.getZ()); | ||
|
||
double followRange = mobEntity.getAttributeValue(EntityAttributes.GENERIC_FOLLOW_RANGE); | ||
double distance = startPos.distanceTo(endPos); | ||
|
||
// If the distance exceeds the follow range, return false | ||
if (distance > followRange) { | ||
return false; | ||
} | ||
|
||
|
||
|
||
|
||
|
||
|
||
BlockHitResult hitResult = world.raycast(new RaycastContext(startPos, endPos, RaycastContext.ShapeType.OUTLINE, RaycastContext.FluidHandling.NONE, mobEntity)); | ||
|
||
BlockPos hitPos = hitResult.getBlockPos(); | ||
BlockState blockState = world.getBlockState(hitPos); | ||
|
||
// Check if the block is transparent | ||
return blockState.isTransparent(world,hitPos) || blockState.isAir()||blockState.isIn(ModBlockTags.TRANSPARENT_FOR_ZOMBIE); | ||
} | ||
} |
53 changes: 53 additions & 0 deletions
53
src/main/java/com/equilibrium/entity/goal/AttackPassiveEntitiesGoal.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,53 @@ | ||
package com.equilibrium.entity.goal; | ||
|
||
import java.util.EnumSet; | ||
import net.minecraft.entity.LivingEntity; | ||
import net.minecraft.entity.ai.goal.Goal; | ||
import net.minecraft.entity.ai.goal.TrackTargetGoal; | ||
import net.minecraft.entity.mob.MobEntity; | ||
import net.minecraft.entity.passive.PassiveEntity; | ||
import net.minecraft.entity.ai.TargetPredicate; | ||
import net.minecraft.util.math.Box; | ||
import org.jetbrains.annotations.Nullable; | ||
|
||
/** | ||
* A target goal that finds a passive entity as the target. | ||
*/ | ||
public class AttackPassiveEntitiesGoal<T extends LivingEntity> extends TrackTargetGoal { | ||
private final Class<T> targetClass; | ||
@Nullable | ||
private LivingEntity targetEntity; | ||
private final TargetPredicate targetPredicate; | ||
|
||
public AttackPassiveEntitiesGoal(MobEntity mob, Class<T> targetClass, boolean checkVisibility, boolean checkCanNavigate) { | ||
super(mob, checkVisibility, checkCanNavigate); | ||
this.targetClass = targetClass; | ||
this.targetPredicate = TargetPredicate.createAttackable().setBaseMaxDistance(this.getFollowRange()); | ||
this.setControls(EnumSet.of(Goal.Control.TARGET)); | ||
} | ||
protected Box getSearchBox(double distance) { | ||
return this.mob.getBoundingBox().expand(distance, 4.0, distance); | ||
} | ||
@Override | ||
public boolean canStart() { | ||
this.findClosestTarget(); | ||
return this.targetEntity != null; | ||
} | ||
|
||
private void findClosestTarget() { | ||
this.targetEntity = this.mob.getWorld().getClosestEntity( | ||
this.mob.getWorld().getEntitiesByClass(this.targetClass, this.getSearchBox(this.getFollowRange()), (entity) -> entity instanceof PassiveEntity), | ||
this.targetPredicate, | ||
this.mob, | ||
this.mob.getX(), | ||
this.mob.getEyeY(), | ||
this.mob.getZ() | ||
); | ||
} | ||
|
||
@Override | ||
public void start() { | ||
this.mob.setTarget(this.targetEntity); | ||
super.start(); | ||
} | ||
} |
Oops, something went wrong.