106 lines
3.3 KiB
Java
106 lines
3.3 KiB
Java
package com.thebrokenrail.twine.entity;
|
|
|
|
import com.thebrokenrail.twine.Twine;
|
|
import net.minecraft.block.Blocks;
|
|
import net.minecraft.entity.ai.TargetFinder;
|
|
import net.minecraft.entity.ai.goal.Goal;
|
|
import net.minecraft.entity.ai.pathing.Path;
|
|
import net.minecraft.entity.mob.MobEntityWithAi;
|
|
import net.minecraft.util.math.BlockPos;
|
|
import net.minecraft.util.math.Vec3d;
|
|
import net.minecraft.world.WorldView;
|
|
import net.minecraft.world.chunk.Chunk;
|
|
import net.minecraft.world.chunk.ChunkStatus;
|
|
|
|
public class FleeEndRodGoal extends Goal {
|
|
private final MobEntityWithAi mob;
|
|
private Vec3d targetPos;
|
|
private Path fleePath;
|
|
|
|
public FleeEndRodGoal(MobEntityWithAi mob) {
|
|
super();
|
|
this.mob = mob;
|
|
}
|
|
|
|
boolean isTargetPos(WorldView world, BlockPos pos) {
|
|
Chunk chunk = world.getChunk(pos.getX() >> 4, pos.getZ() >> 4, ChunkStatus.FULL, false);
|
|
if (chunk == null) {
|
|
return false;
|
|
} else {
|
|
return chunk.getBlockState(pos).isOf(Blocks.END_ROD);
|
|
}
|
|
}
|
|
|
|
private boolean findTargetPos() {
|
|
BlockPos blockPos = mob.getBlockPos();
|
|
BlockPos.Mutable mutable = new BlockPos.Mutable();
|
|
|
|
for (int k = 0; k <= Twine.AI_MAX_Y_DIFFERENCE; k = k > 0 ? -k : 1 - k) {
|
|
for (int l = 0; l < Twine.AI_RANGE; ++l) {
|
|
for (int m = 0; m <= l; m = m > 0 ? -m : 1 - m) {
|
|
for (int n = m < l && m > -l ? l : 0; n <= l; n = n > 0 ? -n : 1 - n) {
|
|
mutable.set(blockPos, m, k - 1, n);
|
|
if (mob.isInWalkTargetRange(mutable) && isTargetPos(mob.world, mutable)) {
|
|
targetPos = new Vec3d(mutable.getX() + 0.5d, mutable.getY(), mutable.getZ() + 0.5d);
|
|
return true;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
return false;
|
|
}
|
|
|
|
private double squaredDistanceTo(Vec3d vector) {
|
|
double d = targetPos.x - vector.x;
|
|
double e = targetPos.y - vector.y;
|
|
double f = targetPos.z - vector.z;
|
|
return d * d + e * e + f * f;
|
|
}
|
|
|
|
@Override
|
|
public boolean canStart() {
|
|
if (findTargetPos()) {
|
|
Vec3d vec3d = TargetFinder.findTargetAwayFrom(mob, Twine.AI_RANGE * 2, Twine.AI_MAX_Y_DIFFERENCE * 2, targetPos);
|
|
if (vec3d == null) {
|
|
return false;
|
|
} else if (squaredDistanceTo(vec3d) < mob.squaredDistanceTo(targetPos)) {
|
|
return false;
|
|
} else {
|
|
fleePath = mob.getNavigation().findPathTo(vec3d.x, vec3d.y, vec3d.z, 0);
|
|
return fleePath != null;
|
|
}
|
|
} else {
|
|
return false;
|
|
}
|
|
}
|
|
|
|
@Override
|
|
public boolean shouldContinue() {
|
|
return !mob.getNavigation().isIdle();
|
|
}
|
|
|
|
@Override
|
|
public void start() {
|
|
mob.getNavigation().startMovingAlong(fleePath, SLOW_SPEED);
|
|
}
|
|
|
|
@Override
|
|
public void stop() {
|
|
targetPos = null;
|
|
}
|
|
|
|
private static final float SLOW_SPEED = 1.25f;
|
|
private static final float FAST_SPEED = 1.5f;
|
|
|
|
@Override
|
|
public void tick() {
|
|
if (squaredDistanceTo(mob.getPos()) < (Twine.AI_RANGE / 2d)) {
|
|
mob.getNavigation().setSpeed(FAST_SPEED);
|
|
} else {
|
|
mob.getNavigation().setSpeed(SLOW_SPEED);
|
|
}
|
|
}
|
|
}
|